sev-guest.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * AMD Secure Encrypted Virtualization (SEV) guest driver interface
  4. *
  5. * Copyright (C) 2021-2024 Advanced Micro Devices, Inc.
  6. *
  7. * Author: Brijesh Singh <brijesh.singh@amd.com>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/types.h>
  12. #include <linux/mutex.h>
  13. #include <linux/io.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/miscdevice.h>
  16. #include <linux/set_memory.h>
  17. #include <linux/fs.h>
  18. #include <linux/tsm.h>
  19. #include <crypto/gcm.h>
  20. #include <linux/psp-sev.h>
  21. #include <linux/sockptr.h>
  22. #include <linux/cleanup.h>
  23. #include <linux/uuid.h>
  24. #include <linux/configfs.h>
  25. #include <linux/mm.h>
  26. #include <uapi/linux/sev-guest.h>
  27. #include <uapi/linux/psp-sev.h>
  28. #include <asm/svm.h>
  29. #include <asm/sev.h>
  30. #define DEVICE_NAME "sev-guest"
  31. #define SVSM_MAX_RETRIES 3
  32. struct snp_guest_dev {
  33. struct device *dev;
  34. struct miscdevice misc;
  35. struct snp_msg_desc *msg_desc;
  36. };
  37. /*
  38. * The VMPCK ID represents the key used by the SNP guest to communicate with the
  39. * SEV firmware in the AMD Secure Processor (ASP, aka PSP). By default, the key
  40. * used will be the key associated with the VMPL at which the guest is running.
  41. * Should the default key be wiped (see snp_disable_vmpck()), this parameter
  42. * allows for using one of the remaining VMPCKs.
  43. */
  44. static int vmpck_id = -1;
  45. module_param(vmpck_id, int, 0444);
  46. MODULE_PARM_DESC(vmpck_id, "The VMPCK ID to use when communicating with the PSP.");
  47. static inline struct snp_guest_dev *to_snp_dev(struct file *file)
  48. {
  49. struct miscdevice *dev = file->private_data;
  50. return container_of(dev, struct snp_guest_dev, misc);
  51. }
  52. struct snp_req_resp {
  53. sockptr_t req_data;
  54. sockptr_t resp_data;
  55. };
  56. static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
  57. {
  58. struct snp_report_req *report_req __free(kfree) = NULL;
  59. struct snp_msg_desc *mdesc = snp_dev->msg_desc;
  60. struct snp_report_resp *report_resp;
  61. struct snp_guest_req req = {};
  62. int rc, resp_len;
  63. if (!arg->req_data || !arg->resp_data)
  64. return -EINVAL;
  65. report_req = kzalloc_obj(*report_req, GFP_KERNEL_ACCOUNT);
  66. if (!report_req)
  67. return -ENOMEM;
  68. if (copy_from_user(report_req, (void __user *)arg->req_data, sizeof(*report_req)))
  69. return -EFAULT;
  70. /*
  71. * The intermediate response buffer is used while decrypting the
  72. * response payload. Make sure that it has enough space to cover the
  73. * authtag.
  74. */
  75. resp_len = sizeof(report_resp->data) + mdesc->ctx->authsize;
  76. report_resp = kzalloc(resp_len, GFP_KERNEL_ACCOUNT);
  77. if (!report_resp)
  78. return -ENOMEM;
  79. req.msg_version = arg->msg_version;
  80. req.msg_type = SNP_MSG_REPORT_REQ;
  81. req.vmpck_id = mdesc->vmpck_id;
  82. req.req_buf = report_req;
  83. req.req_sz = sizeof(*report_req);
  84. req.resp_buf = report_resp->data;
  85. req.resp_sz = resp_len;
  86. req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
  87. rc = snp_send_guest_request(mdesc, &req);
  88. arg->exitinfo2 = req.exitinfo2;
  89. if (rc)
  90. goto e_free;
  91. if (copy_to_user((void __user *)arg->resp_data, report_resp, sizeof(*report_resp)))
  92. rc = -EFAULT;
  93. e_free:
  94. kfree(report_resp);
  95. return rc;
  96. }
  97. static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
  98. {
  99. struct snp_derived_key_resp *derived_key_resp __free(kfree) = NULL;
  100. struct snp_derived_key_req *derived_key_req __free(kfree) = NULL;
  101. struct snp_msg_desc *mdesc = snp_dev->msg_desc;
  102. struct snp_guest_req req = {};
  103. int rc, resp_len;
  104. if (!arg->req_data || !arg->resp_data)
  105. return -EINVAL;
  106. /*
  107. * The intermediate response buffer is used while decrypting the
  108. * response payload. Make sure that it has enough space to cover the
  109. * authtag.
  110. */
  111. resp_len = sizeof(derived_key_resp->data) + mdesc->ctx->authsize;
  112. derived_key_resp = kzalloc(resp_len, GFP_KERNEL_ACCOUNT);
  113. if (!derived_key_resp)
  114. return -ENOMEM;
  115. derived_key_req = kzalloc_obj(*derived_key_req, GFP_KERNEL_ACCOUNT);
  116. if (!derived_key_req)
  117. return -ENOMEM;
  118. if (copy_from_user(derived_key_req, (void __user *)arg->req_data,
  119. sizeof(*derived_key_req)))
  120. return -EFAULT;
  121. req.msg_version = arg->msg_version;
  122. req.msg_type = SNP_MSG_KEY_REQ;
  123. req.vmpck_id = mdesc->vmpck_id;
  124. req.req_buf = derived_key_req;
  125. req.req_sz = sizeof(*derived_key_req);
  126. req.resp_buf = derived_key_resp;
  127. req.resp_sz = resp_len;
  128. req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
  129. rc = snp_send_guest_request(mdesc, &req);
  130. arg->exitinfo2 = req.exitinfo2;
  131. if (!rc) {
  132. if (copy_to_user((void __user *)arg->resp_data, derived_key_resp,
  133. sizeof(derived_key_resp->data)))
  134. rc = -EFAULT;
  135. }
  136. /* The response buffer contains the sensitive data, explicitly clear it. */
  137. memzero_explicit(derived_key_resp, sizeof(*derived_key_resp));
  138. return rc;
  139. }
  140. static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg,
  141. struct snp_req_resp *io)
  142. {
  143. struct snp_ext_report_req *report_req __free(kfree) = NULL;
  144. struct snp_msg_desc *mdesc = snp_dev->msg_desc;
  145. struct snp_report_resp *report_resp;
  146. struct snp_guest_req req = {};
  147. int ret, npages = 0, resp_len;
  148. sockptr_t certs_address;
  149. struct page *page;
  150. if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data))
  151. return -EINVAL;
  152. report_req = kzalloc_obj(*report_req, GFP_KERNEL_ACCOUNT);
  153. if (!report_req)
  154. return -ENOMEM;
  155. if (copy_from_sockptr(report_req, io->req_data, sizeof(*report_req)))
  156. return -EFAULT;
  157. /* caller does not want certificate data */
  158. if (!report_req->certs_len || !report_req->certs_address)
  159. goto cmd;
  160. if (report_req->certs_len > SEV_FW_BLOB_MAX_SIZE ||
  161. !IS_ALIGNED(report_req->certs_len, PAGE_SIZE))
  162. return -EINVAL;
  163. if (sockptr_is_kernel(io->resp_data)) {
  164. certs_address = KERNEL_SOCKPTR((void *)report_req->certs_address);
  165. } else {
  166. certs_address = USER_SOCKPTR((void __user *)report_req->certs_address);
  167. if (!access_ok(certs_address.user, report_req->certs_len))
  168. return -EFAULT;
  169. }
  170. /*
  171. * Initialize the intermediate buffer with all zeros. This buffer
  172. * is used in the guest request message to get the certs blob from
  173. * the host. If host does not supply any certs in it, then copy
  174. * zeros to indicate that certificate data was not provided.
  175. */
  176. npages = report_req->certs_len >> PAGE_SHIFT;
  177. page = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO,
  178. get_order(report_req->certs_len));
  179. if (!page)
  180. return -ENOMEM;
  181. req.certs_data = page_address(page);
  182. ret = set_memory_decrypted((unsigned long)req.certs_data, npages);
  183. if (ret) {
  184. pr_err("failed to mark page shared, ret=%d\n", ret);
  185. __free_pages(page, get_order(report_req->certs_len));
  186. return -EFAULT;
  187. }
  188. cmd:
  189. /*
  190. * The intermediate response buffer is used while decrypting the
  191. * response payload. Make sure that it has enough space to cover the
  192. * authtag.
  193. */
  194. resp_len = sizeof(report_resp->data) + mdesc->ctx->authsize;
  195. report_resp = kzalloc(resp_len, GFP_KERNEL_ACCOUNT);
  196. if (!report_resp) {
  197. ret = -ENOMEM;
  198. goto e_free_data;
  199. }
  200. req.input.data_npages = npages;
  201. req.msg_version = arg->msg_version;
  202. req.msg_type = SNP_MSG_REPORT_REQ;
  203. req.vmpck_id = mdesc->vmpck_id;
  204. req.req_buf = &report_req->data;
  205. req.req_sz = sizeof(report_req->data);
  206. req.resp_buf = report_resp->data;
  207. req.resp_sz = resp_len;
  208. req.exit_code = SVM_VMGEXIT_EXT_GUEST_REQUEST;
  209. ret = snp_send_guest_request(mdesc, &req);
  210. arg->exitinfo2 = req.exitinfo2;
  211. /* If certs length is invalid then copy the returned length */
  212. if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {
  213. report_req->certs_len = req.input.data_npages << PAGE_SHIFT;
  214. if (copy_to_sockptr(io->req_data, report_req, sizeof(*report_req)))
  215. ret = -EFAULT;
  216. }
  217. if (ret)
  218. goto e_free;
  219. if (npages && copy_to_sockptr(certs_address, req.certs_data, report_req->certs_len)) {
  220. ret = -EFAULT;
  221. goto e_free;
  222. }
  223. if (copy_to_sockptr(io->resp_data, report_resp, sizeof(*report_resp)))
  224. ret = -EFAULT;
  225. e_free:
  226. kfree(report_resp);
  227. e_free_data:
  228. if (npages) {
  229. if (set_memory_encrypted((unsigned long)req.certs_data, npages))
  230. WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
  231. else
  232. __free_pages(page, get_order(report_req->certs_len));
  233. }
  234. return ret;
  235. }
  236. static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
  237. {
  238. struct snp_guest_dev *snp_dev = to_snp_dev(file);
  239. void __user *argp = (void __user *)arg;
  240. struct snp_guest_request_ioctl input;
  241. struct snp_req_resp io;
  242. int ret = -ENOTTY;
  243. if (copy_from_user(&input, argp, sizeof(input)))
  244. return -EFAULT;
  245. input.exitinfo2 = 0xff;
  246. /* Message version must be non-zero */
  247. if (!input.msg_version)
  248. return -EINVAL;
  249. switch (ioctl) {
  250. case SNP_GET_REPORT:
  251. ret = get_report(snp_dev, &input);
  252. break;
  253. case SNP_GET_DERIVED_KEY:
  254. ret = get_derived_key(snp_dev, &input);
  255. break;
  256. case SNP_GET_EXT_REPORT:
  257. /*
  258. * As get_ext_report() may be called from the ioctl() path and a
  259. * kernel internal path (configfs-tsm), decorate the passed
  260. * buffers as user pointers.
  261. */
  262. io.req_data = USER_SOCKPTR((void __user *)input.req_data);
  263. io.resp_data = USER_SOCKPTR((void __user *)input.resp_data);
  264. ret = get_ext_report(snp_dev, &input, &io);
  265. break;
  266. default:
  267. break;
  268. }
  269. if (input.exitinfo2 && copy_to_user(argp, &input, sizeof(input)))
  270. return -EFAULT;
  271. return ret;
  272. }
  273. static const struct file_operations snp_guest_fops = {
  274. .owner = THIS_MODULE,
  275. .unlocked_ioctl = snp_guest_ioctl,
  276. };
  277. struct snp_msg_report_resp_hdr {
  278. u32 status;
  279. u32 report_size;
  280. u8 rsvd[24];
  281. };
  282. struct snp_msg_cert_entry {
  283. guid_t guid;
  284. u32 offset;
  285. u32 length;
  286. };
  287. static int sev_svsm_report_new(struct tsm_report *report, void *data)
  288. {
  289. unsigned int rep_len, man_len, certs_len;
  290. struct tsm_report_desc *desc = &report->desc;
  291. struct svsm_attest_call ac = {};
  292. unsigned int retry_count;
  293. void *rep, *man, *certs;
  294. struct svsm_call call;
  295. unsigned int size;
  296. bool try_again;
  297. void *buffer;
  298. u64 call_id;
  299. int ret;
  300. /*
  301. * Allocate pages for the request:
  302. * - Report blob (4K)
  303. * - Manifest blob (4K)
  304. * - Certificate blob (16K)
  305. *
  306. * Above addresses must be 4K aligned
  307. */
  308. rep_len = SZ_4K;
  309. man_len = SZ_4K;
  310. certs_len = SEV_FW_BLOB_MAX_SIZE;
  311. if (guid_is_null(&desc->service_guid)) {
  312. call_id = SVSM_ATTEST_CALL(SVSM_ATTEST_SERVICES);
  313. } else {
  314. export_guid(ac.service_guid, &desc->service_guid);
  315. ac.service_manifest_ver = desc->service_manifest_version;
  316. call_id = SVSM_ATTEST_CALL(SVSM_ATTEST_SINGLE_SERVICE);
  317. }
  318. retry_count = 0;
  319. retry:
  320. memset(&call, 0, sizeof(call));
  321. size = rep_len + man_len + certs_len;
  322. buffer = alloc_pages_exact(size, __GFP_ZERO);
  323. if (!buffer)
  324. return -ENOMEM;
  325. rep = buffer;
  326. ac.report_buf.pa = __pa(rep);
  327. ac.report_buf.len = rep_len;
  328. man = rep + rep_len;
  329. ac.manifest_buf.pa = __pa(man);
  330. ac.manifest_buf.len = man_len;
  331. certs = man + man_len;
  332. ac.certificates_buf.pa = __pa(certs);
  333. ac.certificates_buf.len = certs_len;
  334. ac.nonce.pa = __pa(desc->inblob);
  335. ac.nonce.len = desc->inblob_len;
  336. ret = snp_issue_svsm_attest_req(call_id, &call, &ac);
  337. if (ret) {
  338. free_pages_exact(buffer, size);
  339. switch (call.rax_out) {
  340. case SVSM_ERR_INVALID_PARAMETER:
  341. try_again = false;
  342. if (ac.report_buf.len > rep_len) {
  343. rep_len = PAGE_ALIGN(ac.report_buf.len);
  344. try_again = true;
  345. }
  346. if (ac.manifest_buf.len > man_len) {
  347. man_len = PAGE_ALIGN(ac.manifest_buf.len);
  348. try_again = true;
  349. }
  350. if (ac.certificates_buf.len > certs_len) {
  351. certs_len = PAGE_ALIGN(ac.certificates_buf.len);
  352. try_again = true;
  353. }
  354. /* If one of the buffers wasn't large enough, retry the request */
  355. if (try_again && retry_count < SVSM_MAX_RETRIES) {
  356. retry_count++;
  357. goto retry;
  358. }
  359. return -EINVAL;
  360. default:
  361. pr_err_ratelimited("SVSM attestation request failed (%d / 0x%llx)\n",
  362. ret, call.rax_out);
  363. return -EINVAL;
  364. }
  365. }
  366. /*
  367. * Allocate all the blob memory buffers at once so that the cleanup is
  368. * done for errors that occur after the first allocation (i.e. before
  369. * using no_free_ptr()).
  370. */
  371. rep_len = ac.report_buf.len;
  372. void *rbuf __free(kvfree) = kvzalloc(rep_len, GFP_KERNEL);
  373. man_len = ac.manifest_buf.len;
  374. void *mbuf __free(kvfree) = kvzalloc(man_len, GFP_KERNEL);
  375. certs_len = ac.certificates_buf.len;
  376. void *cbuf __free(kvfree) = certs_len ? kvzalloc(certs_len, GFP_KERNEL) : NULL;
  377. if (!rbuf || !mbuf || (certs_len && !cbuf)) {
  378. free_pages_exact(buffer, size);
  379. return -ENOMEM;
  380. }
  381. memcpy(rbuf, rep, rep_len);
  382. report->outblob = no_free_ptr(rbuf);
  383. report->outblob_len = rep_len;
  384. memcpy(mbuf, man, man_len);
  385. report->manifestblob = no_free_ptr(mbuf);
  386. report->manifestblob_len = man_len;
  387. if (certs_len) {
  388. memcpy(cbuf, certs, certs_len);
  389. report->auxblob = no_free_ptr(cbuf);
  390. report->auxblob_len = certs_len;
  391. }
  392. free_pages_exact(buffer, size);
  393. return 0;
  394. }
  395. static int sev_report_new(struct tsm_report *report, void *data)
  396. {
  397. struct snp_msg_cert_entry *cert_table;
  398. struct tsm_report_desc *desc = &report->desc;
  399. struct snp_guest_dev *snp_dev = data;
  400. struct snp_msg_report_resp_hdr hdr;
  401. const u32 report_size = SZ_4K;
  402. const u32 ext_size = SEV_FW_BLOB_MAX_SIZE;
  403. u32 certs_size, i, size = report_size + ext_size;
  404. int ret;
  405. if (desc->inblob_len != SNP_REPORT_USER_DATA_SIZE)
  406. return -EINVAL;
  407. if (desc->service_provider) {
  408. if (strcmp(desc->service_provider, "svsm"))
  409. return -EINVAL;
  410. return sev_svsm_report_new(report, data);
  411. }
  412. void *buf __free(kvfree) = kvzalloc(size, GFP_KERNEL);
  413. if (!buf)
  414. return -ENOMEM;
  415. cert_table = buf + report_size;
  416. struct snp_ext_report_req ext_req = {
  417. .data = { .vmpl = desc->privlevel },
  418. .certs_address = (__u64)cert_table,
  419. .certs_len = ext_size,
  420. };
  421. memcpy(&ext_req.data.user_data, desc->inblob, desc->inblob_len);
  422. struct snp_guest_request_ioctl input = {
  423. .msg_version = 1,
  424. .req_data = (__u64)&ext_req,
  425. .resp_data = (__u64)buf,
  426. .exitinfo2 = 0xff,
  427. };
  428. struct snp_req_resp io = {
  429. .req_data = KERNEL_SOCKPTR(&ext_req),
  430. .resp_data = KERNEL_SOCKPTR(buf),
  431. };
  432. ret = get_ext_report(snp_dev, &input, &io);
  433. if (ret)
  434. return ret;
  435. memcpy(&hdr, buf, sizeof(hdr));
  436. if (hdr.status == SEV_RET_INVALID_PARAM)
  437. return -EINVAL;
  438. if (hdr.status == SEV_RET_INVALID_KEY)
  439. return -EINVAL;
  440. if (hdr.status)
  441. return -ENXIO;
  442. if ((hdr.report_size + sizeof(hdr)) > report_size)
  443. return -ENOMEM;
  444. void *rbuf __free(kvfree) = kvzalloc(hdr.report_size, GFP_KERNEL);
  445. if (!rbuf)
  446. return -ENOMEM;
  447. memcpy(rbuf, buf + sizeof(hdr), hdr.report_size);
  448. report->outblob = no_free_ptr(rbuf);
  449. report->outblob_len = hdr.report_size;
  450. certs_size = 0;
  451. for (i = 0; i < ext_size / sizeof(struct snp_msg_cert_entry); i++) {
  452. struct snp_msg_cert_entry *ent = &cert_table[i];
  453. if (guid_is_null(&ent->guid) && !ent->offset && !ent->length)
  454. break;
  455. certs_size = max(certs_size, ent->offset + ent->length);
  456. }
  457. /* Suspicious that the response populated entries without populating size */
  458. if (!certs_size && i)
  459. dev_warn_ratelimited(snp_dev->dev, "certificate slots conveyed without size\n");
  460. /* No certs to report */
  461. if (!certs_size)
  462. return 0;
  463. /* Suspicious that the certificate blob size contract was violated
  464. */
  465. if (certs_size > ext_size) {
  466. dev_warn_ratelimited(snp_dev->dev, "certificate data truncated\n");
  467. certs_size = ext_size;
  468. }
  469. void *cbuf __free(kvfree) = kvzalloc(certs_size, GFP_KERNEL);
  470. if (!cbuf)
  471. return -ENOMEM;
  472. memcpy(cbuf, cert_table, certs_size);
  473. report->auxblob = no_free_ptr(cbuf);
  474. report->auxblob_len = certs_size;
  475. return 0;
  476. }
  477. static bool sev_report_attr_visible(int n)
  478. {
  479. switch (n) {
  480. case TSM_REPORT_GENERATION:
  481. case TSM_REPORT_PROVIDER:
  482. case TSM_REPORT_PRIVLEVEL:
  483. case TSM_REPORT_PRIVLEVEL_FLOOR:
  484. return true;
  485. case TSM_REPORT_SERVICE_PROVIDER:
  486. case TSM_REPORT_SERVICE_GUID:
  487. case TSM_REPORT_SERVICE_MANIFEST_VER:
  488. return snp_vmpl;
  489. }
  490. return false;
  491. }
  492. static bool sev_report_bin_attr_visible(int n)
  493. {
  494. switch (n) {
  495. case TSM_REPORT_INBLOB:
  496. case TSM_REPORT_OUTBLOB:
  497. case TSM_REPORT_AUXBLOB:
  498. return true;
  499. case TSM_REPORT_MANIFESTBLOB:
  500. return snp_vmpl;
  501. }
  502. return false;
  503. }
  504. static struct tsm_report_ops sev_tsm_report_ops = {
  505. .name = KBUILD_MODNAME,
  506. .report_new = sev_report_new,
  507. .report_attr_visible = sev_report_attr_visible,
  508. .report_bin_attr_visible = sev_report_bin_attr_visible,
  509. };
  510. static void unregister_sev_tsm(void *data)
  511. {
  512. tsm_report_unregister(&sev_tsm_report_ops);
  513. }
  514. static int __init sev_guest_probe(struct platform_device *pdev)
  515. {
  516. struct device *dev = &pdev->dev;
  517. struct snp_guest_dev *snp_dev;
  518. struct snp_msg_desc *mdesc;
  519. struct miscdevice *misc;
  520. int ret;
  521. BUILD_BUG_ON(sizeof(struct snp_guest_msg) > PAGE_SIZE);
  522. if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
  523. return -ENODEV;
  524. snp_dev = devm_kzalloc(&pdev->dev, sizeof(struct snp_guest_dev), GFP_KERNEL);
  525. if (!snp_dev)
  526. return -ENOMEM;
  527. mdesc = snp_msg_alloc();
  528. if (IS_ERR_OR_NULL(mdesc))
  529. return -ENOMEM;
  530. ret = snp_msg_init(mdesc, vmpck_id);
  531. if (ret)
  532. goto e_msg_init;
  533. platform_set_drvdata(pdev, snp_dev);
  534. snp_dev->dev = dev;
  535. misc = &snp_dev->misc;
  536. misc->minor = MISC_DYNAMIC_MINOR;
  537. misc->name = DEVICE_NAME;
  538. misc->fops = &snp_guest_fops;
  539. /* Set the privlevel_floor attribute based on the vmpck_id */
  540. sev_tsm_report_ops.privlevel_floor = mdesc->vmpck_id;
  541. ret = tsm_report_register(&sev_tsm_report_ops, snp_dev);
  542. if (ret)
  543. goto e_msg_init;
  544. ret = devm_add_action_or_reset(&pdev->dev, unregister_sev_tsm, NULL);
  545. if (ret)
  546. goto e_msg_init;
  547. ret = misc_register(misc);
  548. if (ret)
  549. goto e_msg_init;
  550. snp_dev->msg_desc = mdesc;
  551. dev_info(dev, "Initialized SEV guest driver (using VMPCK%d communication key)\n",
  552. mdesc->vmpck_id);
  553. return 0;
  554. e_msg_init:
  555. snp_msg_free(mdesc);
  556. return ret;
  557. }
  558. static void __exit sev_guest_remove(struct platform_device *pdev)
  559. {
  560. struct snp_guest_dev *snp_dev = platform_get_drvdata(pdev);
  561. snp_msg_free(snp_dev->msg_desc);
  562. misc_deregister(&snp_dev->misc);
  563. }
  564. /*
  565. * This driver is meant to be a common SEV guest interface driver and to
  566. * support any SEV guest API. As such, even though it has been introduced
  567. * with the SEV-SNP support, it is named "sev-guest".
  568. *
  569. * sev_guest_remove() lives in .exit.text. For drivers registered via
  570. * module_platform_driver_probe() this is ok because they cannot get unbound
  571. * at runtime. So mark the driver struct with __refdata to prevent modpost
  572. * triggering a section mismatch warning.
  573. */
  574. static struct platform_driver sev_guest_driver __refdata = {
  575. .remove = __exit_p(sev_guest_remove),
  576. .driver = {
  577. .name = "sev-guest",
  578. },
  579. };
  580. module_platform_driver_probe(sev_guest_driver, sev_guest_probe);
  581. MODULE_AUTHOR("Brijesh Singh <brijesh.singh@amd.com>");
  582. MODULE_LICENSE("GPL");
  583. MODULE_VERSION("1.0.0");
  584. MODULE_DESCRIPTION("AMD SEV Guest Driver");
  585. MODULE_ALIAS("platform:sev-guest");