[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250514184136.238446-2-dionnaglaze@google.com>
Date: Wed, 14 May 2025 18:41:34 +0000
From: Dionna Glaze <dionnaglaze@...gle.com>
To: kvm@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, linux-coco@...ts.linux.dev,
Dionna Glaze <dionnaglaze@...gle.com>, Thomas Lendacky <Thomas.Lendacky@....com>,
Paolo Bonzini <pbonzini@...hat.com>, Joerg Roedel <jroedel@...e.de>, Peter Gonda <pgonda@...gle.com>,
Borislav Petkov <bp@...en8.de>, Sean Christopherson <seanjc@...gle.com>
Subject: [PATCH v4 1/2] kvm: sev: Add SEV-SNP guest request throttling
The AMD-SP is a precious resource that doesn't have a scheduler other
than a mutex lock queue. To avoid customers from causing a DoS, a
mem_enc_ioctl command for rate limiting guest requests is added.
Recommended values are {.interval_ms = 1000, .burst = 1} or
{.interval_ms = 2000, .burst = 2} to average 1 request every second.
You may need to allow 2 requests back to back to allow for the guest
to query the certificate length in an extended guest request without
a pause. The 1 second average is our target for quality of service
since empirical tests show that 64 VMs can concurrently request an
attestation report with a maximum latency of 1 second. We don't
anticipate more concurrency than that for a seldom used request for
a majority well-behaved set of VMs. The majority point is decided as
>64 VMs given the assumed 128 VM count for "extreme load".
Cc: Thomas Lendacky <Thomas.Lendacky@....com>
Cc: Paolo Bonzini <pbonzini@...hat.com>
Cc: Joerg Roedel <jroedel@...e.de>
Cc: Peter Gonda <pgonda@...gle.com>
Cc: Borislav Petkov <bp@...en8.de>
Cc: Sean Christopherson <seanjc@...gle.com>
Signed-off-by: Dionna Glaze <dionnaglaze@...gle.com>
---
.../virt/kvm/x86/amd-memory-encryption.rst | 23 ++++++++++++++
arch/x86/include/uapi/asm/kvm.h | 7 +++++
arch/x86/kvm/svm/sev.c | 31 +++++++++++++++++++
arch/x86/kvm/svm/svm.h | 2 ++
4 files changed, 63 insertions(+)
diff --git a/Documentation/virt/kvm/x86/amd-memory-encryption.rst b/Documentation/virt/kvm/x86/amd-memory-encryption.rst
index 1ddb6a86ce7f..1b5b4fc35aac 100644
--- a/Documentation/virt/kvm/x86/amd-memory-encryption.rst
+++ b/Documentation/virt/kvm/x86/amd-memory-encryption.rst
@@ -572,6 +572,29 @@ Returns: 0 on success, -negative on error
See SNP_LAUNCH_FINISH in the SEV-SNP specification [snp-fw-abi]_ for further
details on the input parameters in ``struct kvm_sev_snp_launch_finish``.
+21. KVM_SEV_SNP_SET_REQUEST_THROTTLE_RATE
+-----------------------------------------
+
+The KVM_SEV_SNP_SET_REQUEST_THROTTLE_RATE command is used to set a per-VM rate
+limit on responding to requests for AMD-SP to process a guest request.
+The AMD-SP is a global resource with limited capacity, so to avoid noisy
+neighbor effects, the host may set a request rate for guests.
+
+Parameters (in): struct kvm_sev_snp_set_request_throttle_rate
+
+Returns: 0 on success, -negative on error
+
+::
+
+ struct kvm_sev_snp_set_request_throttle_rate {
+ __u32 interval_ms;
+ __u32 burst;
+ };
+
+The interval will be translated into jiffies, so if it after transformation
+the interval is 0, the command will return ``-EINVAL``. The ``burst`` value
+must be greater than 0.
+
Device attribute API
====================
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 460306b35a4b..d92242d9b9af 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -708,6 +708,8 @@ enum sev_cmd_id {
KVM_SEV_SNP_LAUNCH_UPDATE,
KVM_SEV_SNP_LAUNCH_FINISH,
+ KVM_SEV_SNP_SET_REQUEST_THROTTLE_RATE,
+
KVM_SEV_NR_MAX,
};
@@ -877,6 +879,11 @@ struct kvm_sev_snp_launch_finish {
__u64 pad1[4];
};
+struct kvm_sev_snp_set_request_throttle_rate {
+ __u32 interval_ms;
+ __u32 burst;
+};
+
#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index a7a7dc507336..febf4b45fddf 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2535,6 +2535,29 @@ static int snp_launch_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
return ret;
}
+static int snp_set_request_throttle_ms(struct kvm *kvm, struct kvm_sev_cmd *argp)
+{
+ struct kvm_sev_info *sev = to_kvm_sev_info(kvm);
+ struct kvm_sev_snp_set_request_throttle_rate params;
+ int ret;
+ u64 jiffies;
+
+ if (!sev_snp_guest(kvm))
+ return -ENOTTY;
+
+ if (copy_from_user(¶ms, u64_to_user_ptr(argp->data), sizeof(params)))
+ return -EFAULT;
+
+ jiffies = (params.interval_ms * HZ) / 1000;
+
+ if (!jiffies || !params.burst)
+ return -EINVAL;
+
+ ratelimit_state_init(&sev->snp_guest_msg_rs, jiffies, params.burst);
+
+ return 0;
+}
+
int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
{
struct kvm_sev_cmd sev_cmd;
@@ -2640,6 +2663,9 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
case KVM_SEV_SNP_LAUNCH_FINISH:
r = snp_launch_finish(kvm, &sev_cmd);
break;
+ case KVM_SEV_SNP_SET_REQUEST_THROTTLE_RATE_MS:
+ r = snp_set_request_throttle_ms(kvm, &sev_cmd);
+ break;
default:
r = -EINVAL;
goto out;
@@ -4015,6 +4041,11 @@ static int snp_handle_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t resp_
mutex_lock(&sev->guest_req_mutex);
+ if (!__ratelimit(&sev->snp_guest_msg_rs)) {
+ rc = SNP_GUEST_VMM_ERR_BUSY;
+ goto out_unlock;
+ }
+
if (kvm_read_guest(kvm, req_gpa, sev->guest_req_buf, PAGE_SIZE)) {
ret = -EIO;
goto out_unlock;
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index f16b068c4228..0a7c8d3a7560 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -112,6 +112,8 @@ struct kvm_sev_info {
void *guest_req_buf; /* Bounce buffer for SNP Guest Request input */
void *guest_resp_buf; /* Bounce buffer for SNP Guest Request output */
struct mutex guest_req_mutex; /* Must acquire before using bounce buffers */
+
+ struct ratelimit_state snp_guest_msg_rs; /* Limit guest requests */
};
struct kvm_svm {
--
2.49.0.1045.g170613ef41-goog
Powered by blists - more mailing lists