Skip to content

Commit

Permalink
Merge tag 'x86-urgent-2025-03-08' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/tip

Pull more x86 fixes from Ingo Molnar:

 - Add more model IDs to the AMD microcode version check, more people
   are hitting these checks

 - Fix a Xen guest boot warning related to AMD northbridge setup

 - Fix SEV guest bugs related to a recent changes in its locking logic

 - Fix a missing definition of PTRS_PER_PMD that assembly builds can hit

* tag 'x86-urgent-2025-03-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/microcode/AMD: Add some forgotten models to the SHA check
  x86/mm: Define PTRS_PER_PMD for assembly code too
  virt: sev-guest: Move SNP Guest Request data pages handling under snp_cmd_mutex
  virt: sev-guest: Allocate request data dynamically
  x86/amd_nb: Use rdmsr_safe() in amd_get_mmconfig_range()
  • Loading branch information
Linus Torvalds committed Mar 8, 2025
2 parents 2e51e0a + 058a6be commit b7c90e3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 43 deletions.
23 changes: 8 additions & 15 deletions arch/x86/coco/sev/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2853,19 +2853,8 @@ struct snp_msg_desc *snp_msg_alloc(void)
if (!mdesc->response)
goto e_free_request;

mdesc->certs_data = alloc_shared_pages(SEV_FW_BLOB_MAX_SIZE);
if (!mdesc->certs_data)
goto e_free_response;

/* initial the input address for guest request */
mdesc->input.req_gpa = __pa(mdesc->request);
mdesc->input.resp_gpa = __pa(mdesc->response);
mdesc->input.data_gpa = __pa(mdesc->certs_data);

return mdesc;

e_free_response:
free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
e_free_request:
free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
e_unmap:
Expand All @@ -2885,7 +2874,6 @@ void snp_msg_free(struct snp_msg_desc *mdesc)
kfree(mdesc->ctx);
free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
free_shared_pages(mdesc->certs_data, SEV_FW_BLOB_MAX_SIZE);
iounmap((__force void __iomem *)mdesc->secrets);

memset(mdesc, 0, sizeof(*mdesc));
Expand Down Expand Up @@ -3054,7 +3042,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
* sequence number must be incremented or the VMPCK must be deleted to
* prevent reuse of the IV.
*/
rc = snp_issue_guest_request(req, &mdesc->input, rio);
rc = snp_issue_guest_request(req, &req->input, rio);
switch (rc) {
case -ENOSPC:
/*
Expand All @@ -3064,7 +3052,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
* order to increment the sequence number and thus avoid
* IV reuse.
*/
override_npages = mdesc->input.data_npages;
override_npages = req->input.data_npages;
req->exit_code = SVM_VMGEXIT_GUEST_REQUEST;

/*
Expand Down Expand Up @@ -3120,7 +3108,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
}

if (override_npages)
mdesc->input.data_npages = override_npages;
req->input.data_npages = override_npages;

return rc;
}
Expand Down Expand Up @@ -3158,6 +3146,11 @@ int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req
*/
memcpy(mdesc->request, &mdesc->secret_request, sizeof(mdesc->secret_request));

/* Initialize the input address for guest request */
req->input.req_gpa = __pa(mdesc->request);
req->input.resp_gpa = __pa(mdesc->response);
req->input.data_gpa = req->certs_data ? __pa(req->certs_data) : 0;

rc = __handle_guest_request(mdesc, req, rio);
if (rc) {
if (rc == -EIO &&
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/include/asm/pgtable-2level_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ typedef union {
#define ARCH_PAGE_TABLE_SYNC_MASK PGTBL_PMD_MODIFIED

/*
* traditional i386 two-level paging structure:
* Traditional i386 two-level paging structure:
*/

#define PGDIR_SHIFT 22
#define PTRS_PER_PGD 1024


/*
* the i386 is two-level, so we don't really have any
* PMD directory physically.
* The i386 is two-level, so we don't really have any
* PMD directory physically:
*/
#define PTRS_PER_PMD 1

#define PTRS_PER_PTE 1024

Expand Down
6 changes: 3 additions & 3 deletions arch/x86/include/asm/sev.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ struct snp_guest_req {
unsigned int vmpck_id;
u8 msg_version;
u8 msg_type;

struct snp_req_data input;
void *certs_data;
};

/*
Expand Down Expand Up @@ -263,9 +266,6 @@ struct snp_msg_desc {
struct snp_guest_msg secret_request, secret_response;

struct snp_secrets_page *secrets;
struct snp_req_data input;

void *certs_data;

struct aesgcm_ctx *ctx;

Expand Down
9 changes: 3 additions & 6 deletions arch/x86/kernel/amd_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,18 @@ bool __init early_is_amd_nb(u32 device)

struct resource *amd_get_mmconfig_range(struct resource *res)
{
u32 address;
u64 base, msr;
unsigned int segn_busn_bits;

if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
return NULL;

/* assume all cpus from fam10h have mmconfig */
if (boot_cpu_data.x86 < 0x10)
/* Assume CPUs from Fam10h have mmconfig, although not all VMs do */
if (boot_cpu_data.x86 < 0x10 ||
rdmsrl_safe(MSR_FAM10H_MMIO_CONF_BASE, &msr))
return NULL;

address = MSR_FAM10H_MMIO_CONF_BASE;
rdmsrl(address, msr);

/* mmconfig is not enabled */
if (!(msr & FAM10H_MMIO_CONF_ENABLE))
return NULL;
Expand Down
6 changes: 6 additions & 0 deletions arch/x86/kernel/cpu/microcode/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,23 +175,29 @@ static bool need_sha_check(u32 cur_rev)
{
switch (cur_rev >> 8) {
case 0x80012: return cur_rev <= 0x800126f; break;
case 0x80082: return cur_rev <= 0x800820f; break;
case 0x83010: return cur_rev <= 0x830107c; break;
case 0x86001: return cur_rev <= 0x860010e; break;
case 0x86081: return cur_rev <= 0x8608108; break;
case 0x87010: return cur_rev <= 0x8701034; break;
case 0x8a000: return cur_rev <= 0x8a0000a; break;
case 0xa0010: return cur_rev <= 0xa00107a; break;
case 0xa0011: return cur_rev <= 0xa0011da; break;
case 0xa0012: return cur_rev <= 0xa001243; break;
case 0xa0082: return cur_rev <= 0xa00820e; break;
case 0xa1011: return cur_rev <= 0xa101153; break;
case 0xa1012: return cur_rev <= 0xa10124e; break;
case 0xa1081: return cur_rev <= 0xa108109; break;
case 0xa2010: return cur_rev <= 0xa20102f; break;
case 0xa2012: return cur_rev <= 0xa201212; break;
case 0xa4041: return cur_rev <= 0xa404109; break;
case 0xa5000: return cur_rev <= 0xa500013; break;
case 0xa6012: return cur_rev <= 0xa60120a; break;
case 0xa7041: return cur_rev <= 0xa704109; break;
case 0xa7052: return cur_rev <= 0xa705208; break;
case 0xa7080: return cur_rev <= 0xa708009; break;
case 0xa70c0: return cur_rev <= 0xa70C009; break;
case 0xaa001: return cur_rev <= 0xaa00116; break;
case 0xaa002: return cur_rev <= 0xaa00218; break;
default: break;
}
Expand Down
58 changes: 43 additions & 15 deletions drivers/virt/coco/sev-guest/sev-guest.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@ struct snp_guest_dev {
struct miscdevice misc;

struct snp_msg_desc *msg_desc;

union {
struct snp_report_req report;
struct snp_derived_key_req derived_key;
struct snp_ext_report_req ext_report;
} req;
};

/*
Expand Down Expand Up @@ -71,7 +65,7 @@ struct snp_req_resp {

static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
{
struct snp_report_req *report_req = &snp_dev->req.report;
struct snp_report_req *report_req __free(kfree) = NULL;
struct snp_msg_desc *mdesc = snp_dev->msg_desc;
struct snp_report_resp *report_resp;
struct snp_guest_req req = {};
Expand All @@ -80,6 +74,10 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
if (!arg->req_data || !arg->resp_data)
return -EINVAL;

report_req = kzalloc(sizeof(*report_req), GFP_KERNEL_ACCOUNT);
if (!report_req)
return -ENOMEM;

if (copy_from_user(report_req, (void __user *)arg->req_data, sizeof(*report_req)))
return -EFAULT;

Expand Down Expand Up @@ -116,7 +114,7 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io

static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
{
struct snp_derived_key_req *derived_key_req = &snp_dev->req.derived_key;
struct snp_derived_key_req *derived_key_req __free(kfree) = NULL;
struct snp_derived_key_resp derived_key_resp = {0};
struct snp_msg_desc *mdesc = snp_dev->msg_desc;
struct snp_guest_req req = {};
Expand All @@ -136,6 +134,10 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
if (sizeof(buf) < resp_len)
return -ENOMEM;

derived_key_req = kzalloc(sizeof(*derived_key_req), GFP_KERNEL_ACCOUNT);
if (!derived_key_req)
return -ENOMEM;

if (copy_from_user(derived_key_req, (void __user *)arg->req_data,
sizeof(*derived_key_req)))
return -EFAULT;
Expand Down Expand Up @@ -168,16 +170,21 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
struct snp_req_resp *io)

{
struct snp_ext_report_req *report_req = &snp_dev->req.ext_report;
struct snp_ext_report_req *report_req __free(kfree) = NULL;
struct snp_msg_desc *mdesc = snp_dev->msg_desc;
struct snp_report_resp *report_resp;
struct snp_guest_req req = {};
int ret, npages = 0, resp_len;
sockptr_t certs_address;
struct page *page;

if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data))
return -EINVAL;

report_req = kzalloc(sizeof(*report_req), GFP_KERNEL_ACCOUNT);
if (!report_req)
return -ENOMEM;

if (copy_from_sockptr(report_req, io->req_data, sizeof(*report_req)))
return -EFAULT;

Expand All @@ -203,8 +210,20 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
* the host. If host does not supply any certs in it, then copy
* zeros to indicate that certificate data was not provided.
*/
memset(mdesc->certs_data, 0, report_req->certs_len);
npages = report_req->certs_len >> PAGE_SHIFT;
page = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO,
get_order(report_req->certs_len));
if (!page)
return -ENOMEM;

req.certs_data = page_address(page);
ret = set_memory_decrypted((unsigned long)req.certs_data, npages);
if (ret) {
pr_err("failed to mark page shared, ret=%d\n", ret);
__free_pages(page, get_order(report_req->certs_len));
return -EFAULT;
}

cmd:
/*
* The intermediate response buffer is used while decrypting the
Expand All @@ -213,10 +232,12 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
*/
resp_len = sizeof(report_resp->data) + mdesc->ctx->authsize;
report_resp = kzalloc(resp_len, GFP_KERNEL_ACCOUNT);
if (!report_resp)
return -ENOMEM;
if (!report_resp) {
ret = -ENOMEM;
goto e_free_data;
}

mdesc->input.data_npages = npages;
req.input.data_npages = npages;

req.msg_version = arg->msg_version;
req.msg_type = SNP_MSG_REPORT_REQ;
Expand All @@ -231,7 +252,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques

/* If certs length is invalid then copy the returned length */
if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {
report_req->certs_len = mdesc->input.data_npages << PAGE_SHIFT;
report_req->certs_len = req.input.data_npages << PAGE_SHIFT;

if (copy_to_sockptr(io->req_data, report_req, sizeof(*report_req)))
ret = -EFAULT;
Expand All @@ -240,7 +261,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
if (ret)
goto e_free;

if (npages && copy_to_sockptr(certs_address, mdesc->certs_data, report_req->certs_len)) {
if (npages && copy_to_sockptr(certs_address, req.certs_data, report_req->certs_len)) {
ret = -EFAULT;
goto e_free;
}
Expand All @@ -250,6 +271,13 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques

e_free:
kfree(report_resp);
e_free_data:
if (npages) {
if (set_memory_encrypted((unsigned long)req.certs_data, npages))
WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
else
__free_pages(page, get_order(report_req->certs_len));
}
return ret;
}

Expand Down

0 comments on commit b7c90e3

Please sign in to comment.