@@ -21,6 +21,11 @@
#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
+
/* Max counts for allocation masks or CBMs. In other words, the size of respective MSRs*/
#define RDT_MAX_L3_MASK_COUNT 128
#define RDT_MAX_L2_MASK_COUNT 48
@@ -29,6 +34,9 @@
#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 {
@@ -69,6 +77,122 @@ struct RDTState {
struct RDTStateClass {
};
+bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+ 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(rdt)) {
+ return false;
+ }
+
+ rdt->active_rmid = rmid;
+
+ alloc = &rdt->rdtstate->allocations[rmid];
+
+ alloc->active_cos = cos_id;
+
+ return true;
+}
+
+uint32_t rdt_read_l3_mask(uint32_t pos)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+
+ uint32_t val = rdt->rdtstate->msr_L3_ia32_mask_n[pos];
+ return val;
+}
+
+uint32_t rdt_read_l2_mask(uint32_t pos)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+
+ uint32_t val = rdt->rdtstate->msr_L2_ia32_mask_n[pos];
+ return val;
+}
+
+uint32_t rdt_read_mba_thrtl(uint32_t pos)
+{
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+
+ uint32_t val = rdt->rdtstate->ia32_L2_qos_ext_bw_thrtl_n[pos];
+ return val;
+}
+
+void rdt_write_msr_l3_mask(uint32_t pos, uint32_t val) {
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+
+ rdt->rdtstate->msr_L3_ia32_mask_n[pos] = val;
+}
+
+void rdt_write_msr_l2_mask(uint32_t pos, uint32_t val) {
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+
+ rdt->rdtstate->msr_L2_ia32_mask_n[pos] = val;
+}
+
+void rdt_write_mba_thrtl(uint32_t pos, uint32_t val) {
+ X86CPU *cpu = X86_CPU(current_cpu);
+ RDTStatePerCore *rdt = cpu->rdt;
+
+ rdt->rdtstate->ia32_L2_qos_ext_bw_thrtl_n[pos] = val;
+}
+
+uint32_t rdt_max_rmid(RDTStatePerCore *rdt)
+{
+ RDTState *rdtdev = rdt->rdtstate;
+ return rdtdev->rmids - 1;
+}
+
+uint64_t rdt_read_event_count(RDTStatePerCore *rdtInstance, uint32_t rmid, uint32_t event_id)
+{
+ CPUState *cs;
+ 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;
+ }
+
+ CPU_FOREACH(cs) {
+ rdtInstance = &rdt->rdtInstances[cs->cpu_index];
+ if (rmid >= rdtInstance->monitors->len) {
+ return QM_CTR_ERROR;
+ }
+ mon = &g_array_index(rdtInstance->monitors, RDTMonitor, rmid);
+ count_l3 += mon->count_l3;
+ count_local += mon->count_local;
+ count_remote += mon->count_remote;
+ }
+
+ switch (event_id) {
+ case RDT_EVENT_L3_OCCUPANCY:
+ return count_l3 == 0 ? QM_CTR_UNAVAILABLE : count_l3;
+ break;
+ case RDT_EVENT_L3_REMOTE_BW:
+ return count_remote == 0 ? QM_CTR_UNAVAILABLE : count_remote;
+ break;
+ case RDT_EVENT_L3_LOCAL_BW:
+ return count_local == 0 ? QM_CTR_UNAVAILABLE : count_local;
+ break;
+ default:
+ return QM_CTR_ERROR;
+ }
+}
+
OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
static Property rdt_properties[] = {
@@ -17,9 +17,25 @@
#ifndef HW_RDT_H
#define HW_RDT_H
+#include <stdbool.h>
+#include <stdint.h>
+
typedef struct RDTState RDTState;
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(RDTStatePerCore *rdt, uint32_t rmid, uint32_t event_id);
+uint32_t rdt_max_rmid(RDTStatePerCore *rdt);
+
#endif