Skip to content

Commit c552941

Browse files
nikunjadbp3tk0v
authored andcommitted
x86/sev: Carve out and export SNP guest messaging init routines
Currently, the sev-guest driver is the only user of SNP guest messaging. All routines for initializing SNP guest messaging are implemented within the sev-guest driver and are not available during early boot. In preparation for adding Secure TSC guest support, carve out APIs to allocate and initialize the guest messaging descriptor context and make it part of coco/sev/core.c. As there is no user of sev_guest_platform_data anymore, remove the structure. Signed-off-by: Nikunj A Dadhania <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Tom Lendacky <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 864884a commit c552941

File tree

5 files changed

+208
-175
lines changed

5 files changed

+208
-175
lines changed

arch/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,7 @@ config AMD_MEM_ENCRYPT
15591559
select ARCH_HAS_CC_PLATFORM
15601560
select X86_MEM_ENCRYPT
15611561
select UNACCEPTED_MEMORY
1562+
select CRYPTO_LIB_AESGCM
15621563
help
15631564
Say yes to enable support for the encryption of system memory.
15641565
This requires an AMD processor that supports Secure Memory

arch/x86/coco/sev/core.c

Lines changed: 177 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/psp-sev.h>
2626
#include <linux/dmi.h>
2727
#include <uapi/linux/sev-guest.h>
28+
#include <crypto/gcm.h>
2829

2930
#include <asm/init.h>
3031
#include <asm/cpu_entry_area.h>
@@ -2580,15 +2581,9 @@ static struct platform_device sev_guest_device = {
25802581

25812582
static int __init snp_init_platform_device(void)
25822583
{
2583-
struct sev_guest_platform_data data;
2584-
25852584
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
25862585
return -ENODEV;
25872586

2588-
data.secrets_gpa = secrets_pa;
2589-
if (platform_device_add_data(&sev_guest_device, &data, sizeof(data)))
2590-
return -ENODEV;
2591-
25922587
if (platform_device_register(&sev_guest_device))
25932588
return -ENODEV;
25942589

@@ -2667,3 +2662,179 @@ static int __init sev_sysfs_init(void)
26672662
}
26682663
arch_initcall(sev_sysfs_init);
26692664
#endif // CONFIG_SYSFS
2665+
2666+
static void free_shared_pages(void *buf, size_t sz)
2667+
{
2668+
unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
2669+
int ret;
2670+
2671+
if (!buf)
2672+
return;
2673+
2674+
ret = set_memory_encrypted((unsigned long)buf, npages);
2675+
if (ret) {
2676+
WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
2677+
return;
2678+
}
2679+
2680+
__free_pages(virt_to_page(buf), get_order(sz));
2681+
}
2682+
2683+
static void *alloc_shared_pages(size_t sz)
2684+
{
2685+
unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
2686+
struct page *page;
2687+
int ret;
2688+
2689+
page = alloc_pages(GFP_KERNEL_ACCOUNT, get_order(sz));
2690+
if (!page)
2691+
return NULL;
2692+
2693+
ret = set_memory_decrypted((unsigned long)page_address(page), npages);
2694+
if (ret) {
2695+
pr_err("failed to mark page shared, ret=%d\n", ret);
2696+
__free_pages(page, get_order(sz));
2697+
return NULL;
2698+
}
2699+
2700+
return page_address(page);
2701+
}
2702+
2703+
static u8 *get_vmpck(int id, struct snp_secrets_page *secrets, u32 **seqno)
2704+
{
2705+
u8 *key = NULL;
2706+
2707+
switch (id) {
2708+
case 0:
2709+
*seqno = &secrets->os_area.msg_seqno_0;
2710+
key = secrets->vmpck0;
2711+
break;
2712+
case 1:
2713+
*seqno = &secrets->os_area.msg_seqno_1;
2714+
key = secrets->vmpck1;
2715+
break;
2716+
case 2:
2717+
*seqno = &secrets->os_area.msg_seqno_2;
2718+
key = secrets->vmpck2;
2719+
break;
2720+
case 3:
2721+
*seqno = &secrets->os_area.msg_seqno_3;
2722+
key = secrets->vmpck3;
2723+
break;
2724+
default:
2725+
break;
2726+
}
2727+
2728+
return key;
2729+
}
2730+
2731+
static struct aesgcm_ctx *snp_init_crypto(u8 *key, size_t keylen)
2732+
{
2733+
struct aesgcm_ctx *ctx;
2734+
2735+
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
2736+
if (!ctx)
2737+
return NULL;
2738+
2739+
if (aesgcm_expandkey(ctx, key, keylen, AUTHTAG_LEN)) {
2740+
pr_err("Crypto context initialization failed\n");
2741+
kfree(ctx);
2742+
return NULL;
2743+
}
2744+
2745+
return ctx;
2746+
}
2747+
2748+
int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id)
2749+
{
2750+
/* Adjust the default VMPCK key based on the executing VMPL level */
2751+
if (vmpck_id == -1)
2752+
vmpck_id = snp_vmpl;
2753+
2754+
mdesc->vmpck = get_vmpck(vmpck_id, mdesc->secrets, &mdesc->os_area_msg_seqno);
2755+
if (!mdesc->vmpck) {
2756+
pr_err("Invalid VMPCK%d communication key\n", vmpck_id);
2757+
return -EINVAL;
2758+
}
2759+
2760+
/* Verify that VMPCK is not zero. */
2761+
if (!memchr_inv(mdesc->vmpck, 0, VMPCK_KEY_LEN)) {
2762+
pr_err("Empty VMPCK%d communication key\n", vmpck_id);
2763+
return -EINVAL;
2764+
}
2765+
2766+
mdesc->vmpck_id = vmpck_id;
2767+
2768+
mdesc->ctx = snp_init_crypto(mdesc->vmpck, VMPCK_KEY_LEN);
2769+
if (!mdesc->ctx)
2770+
return -ENOMEM;
2771+
2772+
return 0;
2773+
}
2774+
EXPORT_SYMBOL_GPL(snp_msg_init);
2775+
2776+
struct snp_msg_desc *snp_msg_alloc(void)
2777+
{
2778+
struct snp_msg_desc *mdesc;
2779+
void __iomem *mem;
2780+
2781+
BUILD_BUG_ON(sizeof(struct snp_guest_msg) > PAGE_SIZE);
2782+
2783+
mdesc = kzalloc(sizeof(struct snp_msg_desc), GFP_KERNEL);
2784+
if (!mdesc)
2785+
return ERR_PTR(-ENOMEM);
2786+
2787+
mem = ioremap_encrypted(secrets_pa, PAGE_SIZE);
2788+
if (!mem)
2789+
goto e_free_mdesc;
2790+
2791+
mdesc->secrets = (__force struct snp_secrets_page *)mem;
2792+
2793+
/* Allocate the shared page used for the request and response message. */
2794+
mdesc->request = alloc_shared_pages(sizeof(struct snp_guest_msg));
2795+
if (!mdesc->request)
2796+
goto e_unmap;
2797+
2798+
mdesc->response = alloc_shared_pages(sizeof(struct snp_guest_msg));
2799+
if (!mdesc->response)
2800+
goto e_free_request;
2801+
2802+
mdesc->certs_data = alloc_shared_pages(SEV_FW_BLOB_MAX_SIZE);
2803+
if (!mdesc->certs_data)
2804+
goto e_free_response;
2805+
2806+
/* initial the input address for guest request */
2807+
mdesc->input.req_gpa = __pa(mdesc->request);
2808+
mdesc->input.resp_gpa = __pa(mdesc->response);
2809+
mdesc->input.data_gpa = __pa(mdesc->certs_data);
2810+
2811+
return mdesc;
2812+
2813+
e_free_response:
2814+
free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
2815+
e_free_request:
2816+
free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
2817+
e_unmap:
2818+
iounmap(mem);
2819+
e_free_mdesc:
2820+
kfree(mdesc);
2821+
2822+
return ERR_PTR(-ENOMEM);
2823+
}
2824+
EXPORT_SYMBOL_GPL(snp_msg_alloc);
2825+
2826+
void snp_msg_free(struct snp_msg_desc *mdesc)
2827+
{
2828+
if (!mdesc)
2829+
return;
2830+
2831+
kfree(mdesc->ctx);
2832+
free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
2833+
free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
2834+
free_shared_pages(mdesc->certs_data, SEV_FW_BLOB_MAX_SIZE);
2835+
iounmap((__force void __iomem *)mdesc->secrets);
2836+
2837+
memset(mdesc, 0, sizeof(*mdesc));
2838+
kfree(mdesc);
2839+
}
2840+
EXPORT_SYMBOL_GPL(snp_msg_free);

arch/x86/include/asm/sev.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <asm/insn.h>
1515
#include <asm/sev-common.h>
1616
#include <asm/coco.h>
17+
#include <asm/set_memory.h>
1718

1819
#define GHCB_PROTOCOL_MIN 1ULL
1920
#define GHCB_PROTOCOL_MAX 2ULL
@@ -170,10 +171,6 @@ struct snp_guest_msg {
170171
u8 payload[PAGE_SIZE - sizeof(struct snp_guest_msg_hdr)];
171172
} __packed;
172173

173-
struct sev_guest_platform_data {
174-
u64 secrets_gpa;
175-
};
176-
177174
struct snp_guest_req {
178175
void *req_buf;
179176
size_t req_sz;
@@ -253,6 +250,7 @@ struct snp_msg_desc {
253250

254251
u32 *os_area_msg_seqno;
255252
u8 *vmpck;
253+
int vmpck_id;
256254
};
257255

258256
/*
@@ -458,6 +456,10 @@ void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot);
458456
void snp_kexec_finish(void);
459457
void snp_kexec_begin(void);
460458

459+
int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id);
460+
struct snp_msg_desc *snp_msg_alloc(void);
461+
void snp_msg_free(struct snp_msg_desc *mdesc);
462+
461463
#else /* !CONFIG_AMD_MEM_ENCRYPT */
462464

463465
#define snp_vmpl 0
@@ -498,6 +500,9 @@ static inline int prepare_pte_enc(struct pte_enc_desc *d) { return 0; }
498500
static inline void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) { }
499501
static inline void snp_kexec_finish(void) { }
500502
static inline void snp_kexec_begin(void) { }
503+
static inline int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id) { return -1; }
504+
static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; }
505+
static inline void snp_msg_free(struct snp_msg_desc *mdesc) { }
501506

502507
#endif /* CONFIG_AMD_MEM_ENCRYPT */
503508

drivers/virt/coco/sev-guest/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ config SEV_GUEST
22
tristate "AMD SEV Guest driver"
33
default m
44
depends on AMD_MEM_ENCRYPT
5-
select CRYPTO_LIB_AESGCM
65
select TSM_REPORTS
76
help
87
SEV-SNP firmware provides the guest a mechanism to communicate with

0 commit comments

Comments
 (0)