From: Hendrik Wuethrich <whendrik@google.com>
To: qemu-devel@nongnu.org, eduardo@habkost.net,
richard.henderson@linaro.org, marcel.apfelbaum@gmail.com,
mst@redhat.com, pbonzini@redhat.com, zhao1.liu@intel.com,
xiaoyao.li@intel.com, Jonathan.Cameron@huawei.com,
v6-0000-cover-letter.patch@google.com
Cc: peternewman@google.com, Hendrik Wuethrich <whendrik@google.com>
Subject: [PATCH v6 3/8] i386: Add RDT functionality
Date: Fri, 28 Feb 2025 20:04:48 +0000 [thread overview]
Message-ID: <20250228200453.45173-3-whendrik@google.com> (raw)
In-Reply-To: <20250228200453.45173-1-whendrik@google.com>
Add RDT code to Associate CLOSID with RMID / set RMID for monitoring,
write COS, and read monitoring data. This patch does not add code for
the guest to interact through these things with MSRs, only the actual
ability for the RDT device to do them.
Signed-off-by: Hendrik Wuethrich <whendrik@google.com>
---
hw/i386/rdt.c | 145 ++++++++++++++++++++++++++++++++++++++++++
include/hw/i386/rdt.h | 16 +++++
2 files changed, 161 insertions(+)
diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
index 498c7b70ad..32ef1ee124 100644
--- a/hw/i386/rdt.c
+++ b/hw/i386/rdt.c
@@ -22,9 +22,17 @@
#include "qom/object.h"
#include "target/i386/cpu.h"
+/* RDT Monitoring Event Codes */
+#define RDT_EVENT_L3_OCCUPANCY 1
+#define RDT_EVENT_L3_REMOTE_BW 2
+#define RDT_EVENT_L3_LOCAL_BW 3
+
#define TYPE_RDT "rdt"
#define RDT_NUM_RMID_PROP "rmids"
+#define QM_CTR_ERROR (1ULL << 63)
+#define QM_CTR_UNAVAILABLE (1ULL << 62)
+
OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
struct RDTMonitor {
@@ -73,6 +81,143 @@ struct RDTState {
struct RDTStateClass {
};
+bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdtStatePerL3Cache = cpu->rdtStatePerL3Cache;
+ RDTStatePerCore *rdtPerCore = cpu->rdtPerCore;
+ RDTAllocation *alloc;
+
+ uint32_t cos_id = (msr_ia32_pqr_assoc & 0xffff0000) >> 16;
+ uint32_t rmid = msr_ia32_pqr_assoc & 0xffff;
+
+ if (cos_id > RDT_MAX_L3_MASK_COUNT || cos_id > RDT_MAX_L2_MASK_COUNT ||
+ cos_id > RDT_MAX_MBA_THRTL_COUNT || rmid > rdt_max_rmid(rdtStatePerL3Cache)) {
+ return false;
+ }
+
+ qemu_mutex_lock(&rdtPerCore->lock);
+ qemu_mutex_lock(&rdtStatePerL3Cache->lock);
+
+ rdtPerCore->active_rmid = rmid;
+
+ alloc = &rdtStatePerL3Cache->rdtstate->allocations[rmid];
+
+ alloc->active_cos = cos_id;
+
+ qemu_mutex_unlock(&rdtStatePerL3Cache->lock);
+ qemu_mutex_unlock(&rdtPerCore->lock);
+
+ return true;
+}
+
+uint32_t rdt_read_l3_mask(uint32_t pos)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdt = cpu->rdtStatePerL3Cache;
+
+ qemu_mutex_lock(&rdt->lock);
+ return rdt->msr_L3_ia32_mask_n[pos];
+ qemu_mutex_unlock(&rdt->lock);
+}
+
+uint32_t rdt_read_l2_mask(uint32_t pos)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdt = cpu->rdtStatePerL3Cache;
+
+ qemu_mutex_lock(&rdt->lock);
+ return rdt->msr_L2_ia32_mask_n[pos];
+ qemu_mutex_unlock(&rdt->lock);
+}
+
+uint32_t rdt_read_mba_thrtl(uint32_t pos)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdt = cpu->rdtStatePerL3Cache;
+
+ qemu_mutex_lock(&rdt->lock);
+ return rdt->ia32_L2_qos_ext_bw_thrtl_n[pos];
+ qemu_mutex_unlock(&rdt->lock);
+}
+
+void rdt_write_msr_l3_mask(uint32_t pos, uint32_t val)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdt = cpu->rdtStatePerL3Cache;
+
+ qemu_mutex_lock(&rdt->lock);
+ rdt->msr_L3_ia32_mask_n[pos] = val;
+ qemu_mutex_unlock(&rdt->lock);
+}
+
+void rdt_write_msr_l2_mask(uint32_t pos, uint32_t val)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdt = cpu->rdtStatePerL3Cache;
+
+ qemu_mutex_lock(&rdt->lock);
+ rdt->msr_L2_ia32_mask_n[pos] = val;
+ qemu_mutex_unlock(&rdt->lock);
+}
+
+void rdt_write_mba_thrtl(uint32_t pos, uint32_t val)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerL3Cache *rdt = cpu->rdtStatePerL3Cache;
+
+ qemu_mutex_lock(&rdt->lock);
+ rdt->ia32_L2_qos_ext_bw_thrtl_n[pos] = val;
+ qemu_mutex_unlock(&rdt->lock);
+}
+
+uint32_t rdt_max_rmid(RDTStatePerL3Cache *rdt)
+{
+ RDTState *rdtdev = rdt->rdtstate;
+ return rdtdev->rmids - 1;
+}
+
+uint64_t rdt_read_event_count(RDTStatePerL3Cache *rdtInstance,
+ uint32_t rmid, uint32_t event_id)
+{
+ RDTMonitor *mon;
+ RDTState *rdt = rdtInstance->rdtstate;
+
+ uint32_t count_l3 = 0;
+ uint32_t count_local = 0;
+ uint32_t count_remote = 0;
+
+ if (!rdt) {
+ return 0;
+ }
+
+ qemu_mutex_lock(&rdtInstance->lock);
+
+ for (int i = 0; i < rdt->l3_caches; i++) {
+ rdtInstance = &rdt->rdtInstances[i];
+ if (rmid >= rdtInstance->rdtstate->rmids) {
+ return QM_CTR_ERROR;
+ }
+ mon = &rdtInstance->monitors[rmid];
+ count_l3 += mon->count_l3;
+ count_local += mon->count_local;
+ count_remote += mon->count_remote;
+ }
+
+ qemu_mutex_unlock(&rdtInstance->lock);
+
+ switch (event_id) {
+ case RDT_EVENT_L3_OCCUPANCY:
+ return count_l3 == 0 ? QM_CTR_UNAVAILABLE : count_l3;
+ case RDT_EVENT_L3_REMOTE_BW:
+ return count_remote == 0 ? QM_CTR_UNAVAILABLE : count_remote;
+ case RDT_EVENT_L3_LOCAL_BW:
+ return count_local == 0 ? QM_CTR_UNAVAILABLE : count_local;
+ default:
+ return QM_CTR_ERROR;
+ }
+}
+
static inline int16_t cache_ids_contain(uint32_t current_ids[],
uint16_t size, uint32_t id) {
for (int i = 0; i < size; i++) {
diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
index 1f99f98f7f..d087627499 100644
--- a/include/hw/i386/rdt.h
+++ b/include/hw/i386/rdt.h
@@ -17,6 +17,9 @@
#ifndef HW_RDT_H
#define HW_RDT_H
+#include <stdbool.h>
+#include <stdint.h>
+
/* Max counts for allocation masks or CBMs. In other words, the size of
* respective MSRs.
* L3_MASK and L3_mask are architectural limitations. THRTL_COUNT is just
@@ -32,4 +35,17 @@ typedef struct RDTStatePerCore RDTStatePerCore;
typedef struct RDTMonitor RDTMonitor;
typedef struct RDTAllocation RDTAllocation;
+bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc);
+
+void rdt_write_msr_l3_mask(uint32_t pos, uint32_t val);
+void rdt_write_msr_l2_mask(uint32_t pos, uint32_t val);
+void rdt_write_mba_thrtl(uint32_t pos, uint32_t val);
+
+uint32_t rdt_read_l3_mask(uint32_t pos);
+uint32_t rdt_read_l2_mask(uint32_t pos);
+uint32_t rdt_read_mba_thrtl(uint32_t pos);
+
+uint64_t rdt_read_event_count(RDTStatePerL3Cache *rdt, uint32_t rmid, uint32_t event_id);
+uint32_t rdt_max_rmid(RDTStatePerL3Cache *rdt);
+
#endif
--
2.48.1.711.g2feabab25a-goog
next prev parent reply other threads:[~2025-02-28 20:07 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-28 20:04 [PATCH v6 1/8] i386: Add Intel RDT device and State to config Hendrik Wuethrich
2025-02-28 20:04 ` [PATCH v6 2/8] i386: Add init and realize functionality for RDT device Hendrik Wuethrich
2025-02-28 20:04 ` Hendrik Wuethrich [this message]
2025-02-28 20:04 ` [PATCH v6 4/8] i386: Add RDT device interface through MSRs Hendrik Wuethrich
2025-02-28 20:04 ` [PATCH v6 5/8] i386: Add CPUID enumeration for RDT Hendrik Wuethrich
2025-02-28 20:04 ` [PATCH v6 6/8] i386: Add RDT feature flags Hendrik Wuethrich
2025-02-28 20:04 ` [PATCH v6 7/8] i386/cpu: Adjust CPUID level for RDT features Hendrik Wuethrich
2025-02-28 20:04 ` [PATCH v6 8/8] i386/cpu: Adjust level for RDT on full_cpuid_auto_level Hendrik Wuethrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250228200453.45173-3-whendrik@google.com \
--to=whendrik@google.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=eduardo@habkost.net \
--cc=marcel.apfelbaum@gmail.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peternewman@google.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=v6-0000-cover-letter.patch@google.com \
--cc=xiaoyao.li@intel.com \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).