qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux
@ 2024-07-19 16:29 Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 1/9] Add Intel RDT device to config Hendrik Wuethrich
                   ` (8 more replies)
  0 siblings, 9 replies; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, Hendrik Wüthrich

From: Hendrik Wüthrich <whendrik@google.com>

The aim of this patch series is to emulate Intel RDT features in order
to make testing of the linux Resctrl subsystem possible with Qemu.

A branch with the patches applied can be found at:
https://github.com/Gray-Colors/Intel_RDT_patches_applied

The changes made introduce the following features:

* Feature enumeration for Intel RDT allocation.
* Feature enumeration for Intel RDT monitoring.
* Intel RDT monitoring system interface.
* Intel RDT allocation system interface.

By adding these features, a barebones implementation most of the RDT
state and MSRs is introduced, which can be enabled through qemu
command line flags.
The features missing for a faithful recreation of RDT are CDP and
non-linear MBA throttle, as well as the possibility to configure
various values through the command line, as some properties can be
different across different machines. For increased ease of use, the
correct features should be automatically enabled on machines that
support RDT functionality.
The missing features mentioned above will be implemented in the
following order:

* Expand feature set for RDT allocation to include CDP and non-linear
 MBA throttle
* Allow for command line configuration of some values, such as the L3
 CBM length
* Automatically enable RDT on machines that officially support it.

Will NOT be implemented
* Tests to simulate interaction with the host by the guest

Command line examples assuming entire patch series is applied (This
requires a kernel with Resctrl enabled):

To emulate Intel RDT features:

Currently, it is necessary to force the RDT options on in qemu, as it is
not automatically enabled for any machines. An example would be the
following:
- Skylake-Server,+l3-cmt,+rdt-m,+rdt-a,+mba,+l3-cat,+l2-cat

Just enabling RDT in qemu won't really help, though. The following
option allows resctrl in the kernel:
- Kernel options: rdt=mbmlocal,mbmtotal,cmt,mba,l2cat,l3cat

To use Resctrl in the Qemu, please refer to:
https://docs.kernel.org/arch/x86/resctrl.html

‪Hendrik Wüthrich (9):
  Add Intel RDT device to config.
  Add state for RDT device.
  Add init and realize funciontality for RDT device.
  Add RDT functionality
  Add RDT device interface through MSRs
  Add CPUID enumeration for RDT
  Add RDT feature flags.
  Adjust CPUID level for RDT features
  Adjust level for RDT on full_cpuid_auto_level

 hw/i386/Kconfig                      |   4 +
 hw/i386/meson.build                  |   1 +
 hw/i386/rdt.c                        | 271 +++++++++++++++++++++++++++
 include/hw/i386/rdt.h                |  60 ++++++
 target/i386/cpu.c                    | 134 ++++++++++++-
 target/i386/cpu.h                    |  26 +++
 target/i386/tcg/sysemu/misc_helper.c |  80 ++++++++
 7 files changed, 574 insertions(+), 2 deletions(-)
 create mode 100644 hw/i386/rdt.c
 create mode 100644 include/hw/i386/rdt.h

-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v1 1/9] Add Intel RDT device to config.
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-26 10:24   ` Jonathan Cameron via
  2024-07-19 16:29 ` [PATCH v1 2/9] Add state for RDT device Hendrik Wuethrich
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Change config to show RDT, add minimal code to the rdt.c module to make
sure things still compile.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 hw/i386/Kconfig       |  4 ++++
 hw/i386/meson.build   |  1 +
 hw/i386/rdt.c         | 49 +++++++++++++++++++++++++++++++++++++++++++
 include/hw/i386/rdt.h | 12 +++++++++++
 4 files changed, 66 insertions(+)
 create mode 100644 hw/i386/rdt.c
 create mode 100644 include/hw/i386/rdt.h

diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index f4a33b6c08..4dd05ed6f2 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -10,6 +10,9 @@ config SGX
     bool
     depends on KVM
 
+config RDT
+    bool
+
 config PC
     bool
     imply APPLESMC
@@ -26,6 +29,7 @@ config PC
     imply QXL
     imply SEV
     imply SGX
+    imply RDT
     imply TEST_DEVICES
     imply TPM_CRB
     imply TPM_TIS_ISA
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 03aad10df7..fdbf5962b5 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -21,6 +21,7 @@ i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
 i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c'))
 i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c','sgx.c'),
                                 if_false: files('sgx-stub.c'))
+i386_ss.add(when: 'CONFIG_RDT', if_true: files('rdt.c'))
 
 i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
 i386_ss.add(when: 'CONFIG_PC', if_true: files(
diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
new file mode 100644
index 0000000000..0a5e95606b
--- /dev/null
+++ b/hw/i386/rdt.c
@@ -0,0 +1,49 @@
+#include "qemu/osdep.h"
+#include "hw/i386/rdt.h"
+#include <stdint.h>
+#include "hw/qdev-properties.h"
+#include "qemu/typedefs.h"
+#include "qom/object.h"
+#include "target/i386/cpu.h"
+#include "hw/isa/isa.h"
+
+#define TYPE_RDT "rdt"
+
+OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
+
+struct RDTState {
+    ISADevice parent;
+};
+
+struct RDTStateClass { };
+
+OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
+
+static Property rdt_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rdt_init(Object *obj)
+{
+}
+
+static void rdt_realize(DeviceState *dev, Error **errp)
+{
+}
+
+static void rdt_finalize(Object *obj)
+{
+}
+
+static void rdt_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->hotpluggable = false;
+    dc->desc = "RDT";
+    dc->user_creatable = true;
+    dc->realize = rdt_realize;
+
+    device_class_set_props(dc, rdt_properties);
+}
+
diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
new file mode 100644
index 0000000000..45e34d3103
--- /dev/null
+++ b/include/hw/i386/rdt.h
@@ -0,0 +1,12 @@
+#ifndef HW_RDT_H
+#define HW_RDT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct RDTState RDTState;
+typedef struct RDTStateInstance RDTStateInstance;
+typedef struct RDTMonitor RDTMonitor;
+typedef struct RDTAllocation RDTAllocation;
+
+#endif
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 2/9] Add state for RDT device.
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 1/9] Add Intel RDT device to config Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-26 10:33   ` Jonathan Cameron via
  2024-07-19 16:29 ` [PATCH v1 3/9] Add init and realize funciontality " Hendrik Wuethrich
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Add structures and variables needed to emulate Intel RDT, including
module-internal sturctures and state in ArchCPU. No functionality yet.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 hw/i386/rdt.c     | 33 +++++++++++++++++++++++++++++++++
 target/i386/cpu.h |  5 +++++
 2 files changed, 38 insertions(+)

diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
index 0a5e95606b..cf246ab835 100644
--- a/hw/i386/rdt.c
+++ b/hw/i386/rdt.c
@@ -7,12 +7,44 @@
 #include "target/i386/cpu.h"
 #include "hw/isa/isa.h"
 
+/* Max counts for allocation masks or CBMs. In other words, the size of respective MSRs*/
+#define MAX_L3_MASK_COUNT      128
+#define MAX_L2_MASK_COUNT      48
+#define MAX_MBA_THRTL_COUNT    31
+
 #define TYPE_RDT "rdt"
+#define RDT_NUM_RMID_PROP "rmids"
 
 OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
 
+struct RDTMonitor {
+    uint64_t count_local;
+    uint64_t count_remote;
+    uint64_t count_l3;
+};
+
+struct RDTAllocation {
+    uint32_t active_cos;
+};
+
+struct RDTStateInstance {
+    uint32_t active_rmid;
+    GArray *monitors;
+
+    RDTState *rdtstate;
+};
+
 struct RDTState {
     ISADevice parent;
+
+    uint32_t rmids;
+
+    GArray *rdtInstances;
+    GArray *allocations;
+
+    uint32_t msr_L3_ia32_mask_n[MAX_L3_MASK_COUNT];
+    uint32_t msr_L2_ia32_mask_n[MAX_L2_MASK_COUNT];
+    uint32_t ia32_L2_qos_ext_bw_thrtl_n[MAX_MBA_THRTL_COUNT];
 };
 
 struct RDTStateClass { };
@@ -20,6 +52,7 @@ struct RDTStateClass { };
 OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
 
 static Property rdt_properties[] = {
+    DEFINE_PROP_UINT32(RDT_NUM_RMID_PROP, RDTState, rmids, 256),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 1e121acef5..bd0bbb75f2 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1987,6 +1987,8 @@ typedef struct CPUArchState {
 
 struct kvm_msrs;
 
+struct RDTState;
+struct rdtStateInstance;
 /**
  * X86CPU:
  * @env: #CPUX86State
@@ -2143,6 +2145,9 @@ struct ArchCPU {
     struct MemoryRegion *cpu_as_root, *cpu_as_mem, *smram;
     Notifier machine_done;
 
+    /* Help the RDT MSRs find the RDT device */
+    struct RDTStateInstance *rdt;
+
     struct kvm_msrs *kvm_msr_buf;
 
     int32_t node_id; /* NUMA node this CPU belongs to */
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 3/9] Add init and realize funciontality for RDT device.
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 1/9] Add Intel RDT device to config Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 2/9] Add state for RDT device Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-26 10:41   ` Jonathan Cameron via
  2024-07-26 10:42   ` Jonathan Cameron via
  2024-07-19 16:29 ` [PATCH v1 4/9] Add RDT functionality Hendrik Wuethrich
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Add code to initialize all necessary state for the RDT device.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 hw/i386/rdt.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
index cf246ab835..259dafc963 100644
--- a/hw/i386/rdt.c
+++ b/hw/i386/rdt.c
@@ -62,10 +62,38 @@ static void rdt_init(Object *obj)
 
 static void rdt_realize(DeviceState *dev, Error **errp)
 {
+    CPUState *cs = first_cpu;
+
+    RDTState *rdtDev = RDT(dev);
+    rdtDev->rdtInstances = g_array_new(false, true, sizeof(RDTStateInstance));
+    g_array_set_size(rdtDev->rdtInstances, cs->nr_cores);
+    CPU_FOREACH(cs) {
+        RDTStateInstance *rdt = &g_array_index(rdtDev->rdtInstances, RDTStateInstance, cs->cpu_index);
+
+        X86CPU *cpu = X86_CPU(cs);
+        rdt->rdtstate = rdtDev;
+        cpu->rdt = rdt;
+
+        rdt->monitors = g_array_new(false, true, sizeof(RDTMonitor));
+        rdt->rdtstate->allocations = g_array_new(false, true, sizeof(RDTAllocation));
+
+        g_array_set_size(rdt->monitors, rdtDev->rmids);
+        g_array_set_size(rdt->rdtstate->allocations, rdtDev->rmids);
+    }
 }
 
 static void rdt_finalize(Object *obj)
 {
+    CPUState *cs;
+    RDTState *rdt = RDT(obj);
+
+    CPU_FOREACH(cs) {
+        RDTStateInstance *rdtInstance = &g_array_index(rdt->rdtInstances, RDTStateInstance, cs->cpu_index);
+        g_array_free(rdtInstance->monitors, true);
+        g_array_free(rdtInstance->rdtstate->allocations, true);
+    }
+
+    g_array_free(rdt->rdtInstances, true);
 }
 
 static void rdt_class_init(ObjectClass *klass, void *data)
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 4/9] Add RDT functionality
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
                   ` (2 preceding siblings ...)
  2024-07-19 16:29 ` [PATCH v1 3/9] Add init and realize funciontality " Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-26 10:51   ` Jonathan Cameron via
  2024-07-19 16:29 ` [PATCH v1 5/9] Add RDT device interface through MSRs Hendrik Wuethrich
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <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 Wüthrich <whendrik@google.com>
---
 hw/i386/rdt.c         | 124 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/i386/rdt.h |  13 +++++
 2 files changed, 137 insertions(+)

diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
index 259dafc963..77b7b4f2d4 100644
--- a/hw/i386/rdt.c
+++ b/hw/i386/rdt.c
@@ -7,6 +7,11 @@
 #include "target/i386/cpu.h"
 #include "hw/isa/isa.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 MAX_L3_MASK_COUNT      128
 #define MAX_L2_MASK_COUNT      48
@@ -15,6 +20,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 {
@@ -49,6 +57,122 @@ struct RDTState {
 
 struct RDTStateClass { };
 
+bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
+    X86CPU *cpu = X86_CPU(current_cpu);
+    RDTStateInstance *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 > MAX_L3_MASK_COUNT || cos_id > MAX_L2_MASK_COUNT ||
+    cos_id > MAX_MBA_THRTL_COUNT || rmid > rdt_max_rmid(rdt)) {
+        return false;
+    }
+
+    rdt->active_rmid = rmid;
+
+    alloc = &g_array_index(rdt->rdtstate->allocations, RDTAllocation, rmid);
+
+    alloc->active_cos = cos_id;
+
+    return true;
+}
+
+uint32_t rdt_read_l3_mask(uint32_t pos)
+{
+    X86CPU *cpu = X86_CPU(current_cpu);
+    RDTStateInstance *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);
+    RDTStateInstance *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);
+    RDTStateInstance *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);
+    RDTStateInstance *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);
+    RDTStateInstance *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);
+    RDTStateInstance *rdt = cpu->rdt;
+
+    rdt->rdtstate->ia32_L2_qos_ext_bw_thrtl_n[pos] = val;
+}
+
+uint32_t rdt_max_rmid(RDTStateInstance *rdt)
+{
+    RDTState *rdtdev = rdt->rdtstate;
+    return rdtdev->rmids - 1;
+}
+
+uint64_t rdt_read_event_count(RDTStateInstance *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 = &g_array_index(rdt->rdtInstances, RDTStateInstance, 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[] = {
diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
index 45e34d3103..8092c5f290 100644
--- a/include/hw/i386/rdt.h
+++ b/include/hw/i386/rdt.h
@@ -10,3 +10,16 @@ typedef struct RDTMonitor RDTMonitor;
 typedef struct RDTAllocation RDTAllocation;
 
 #endif
+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(RDTStateInstance *rdt, uint32_t rmid, uint32_t event_id);
+uint32_t rdt_max_rmid(RDTStateInstance *rdt);
+
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 5/9] Add RDT device interface through MSRs
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
                   ` (3 preceding siblings ...)
  2024-07-19 16:29 ` [PATCH v1 4/9] Add RDT functionality Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-26 10:57   ` Jonathan Cameron via
  2024-07-19 16:29 ` [PATCH v1 6/9] Add CPUID enumeration for RDT Hendrik Wuethrich
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Implement rdmsr and wrmsr for the following MSRs:
* MSR_IA32_PQR_ASSOC
* MSR_IA32_QM_EVTSEL
* MSR_IA32_QM_CTR
* IA32_L3_QOS_Mask_n
* IA32_L2_QOS_Mask_n
* IA32_L2_QoS_Ext_BW_Thrtl_n

This allows for the guest to call RDT-internal functions to
associate an RMID with a CLOSID / set an active RMID for
monitoring, read monitoring data, and set classes of service.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 hw/i386/rdt.c                        |  8 +++
 include/hw/i386/rdt.h                |  8 ++-
 target/i386/cpu.h                    | 14 +++++
 target/i386/tcg/sysemu/misc_helper.c | 80 ++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
index 77b7b4f2d4..0d0e5751fc 100644
--- a/hw/i386/rdt.c
+++ b/hw/i386/rdt.c
@@ -17,6 +17,10 @@
 #define MAX_L2_MASK_COUNT      48
 #define MAX_MBA_THRTL_COUNT    31
 
+#define CPUID_10_1_EDX_COS_MAX          MAX_L3_MASK_COUNT
+#define CPUID_10_2_EDX_COS_MAX          MAX_L2_MASK_COUNT
+#define CPUID_10_3_EDX_COS_MAX          MAX_MBA_THRTL_COUNT
+
 #define TYPE_RDT "rdt"
 #define RDT_NUM_RMID_PROP "rmids"
 
@@ -57,6 +61,10 @@ struct RDTState {
 
 struct RDTStateClass { };
 
+uint32_t rdt_get_cpuid_10_1_edx_cos_max(void) { return CPUID_10_1_EDX_COS_MAX; }
+uint32_t rdt_get_cpuid_10_2_edx_cos_max(void) { return CPUID_10_2_EDX_COS_MAX; }
+uint32_t rdt_get_cpuid_10_3_edx_cos_max(void) { return CPUID_10_3_EDX_COS_MAX; }
+
 bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
     X86CPU *cpu = X86_CPU(current_cpu);
     RDTStateInstance *rdt = cpu->rdt;
diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
index 8092c5f290..51d36822f0 100644
--- a/include/hw/i386/rdt.h
+++ b/include/hw/i386/rdt.h
@@ -9,7 +9,12 @@ typedef struct RDTStateInstance RDTStateInstance;
 typedef struct RDTMonitor RDTMonitor;
 typedef struct RDTAllocation RDTAllocation;
 
-#endif
+uint32_t rdt_get_cpuid_10_1_edx_cos_max(void);
+
+uint32_t rdt_get_cpuid_10_2_edx_cos_max(void);
+
+uint32_t rdt_get_cpuid_10_3_edx_cos_max(void);
+
 bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc);
 
 void rdt_write_msr_l3_mask(uint32_t pos, uint32_t val);
@@ -23,3 +28,4 @@ uint32_t rdt_read_mba_thrtl(uint32_t pos);
 uint64_t rdt_read_event_count(RDTStateInstance *rdt, uint32_t rmid, uint32_t event_id);
 uint32_t rdt_max_rmid(RDTStateInstance *rdt);
 
+#endif
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index bd0bbb75f2..0b3aca2d02 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -574,6 +574,17 @@ typedef enum X86Seg {
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
 #define MSR_IA32_VMX_VMFUNC             0x00000491
 
+#define MSR_IA32_QM_EVTSEL                  0x0c8d
+#define MSR_IA32_QM_CTR                     0x0c8e
+#define MSR_IA32_PQR_ASSOC                  0x0c8f
+
+#define MSR_IA32_L3_CBM_BASE                0x0c90
+#define MSR_IA32_L3_MASKS_END               0x0d0f
+#define MSR_IA32_L2_CBM_BASE                0x0d10
+#define MSR_IA32_L2_CBM_END                 0x0d4f
+#define MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE   0xd50
+#define MSR_IA32_L2_QOS_Ext_BW_Thrtl_END    0xd80
+
 #define MSR_APIC_START                  0x00000800
 #define MSR_APIC_END                    0x000008ff
 
@@ -1778,6 +1789,9 @@ typedef struct CPUArchState {
     uint64_t msr_ia32_feature_control;
     uint64_t msr_ia32_sgxlepubkeyhash[4];
 
+    uint64_t msr_ia32_qm_evtsel;
+    uint64_t msr_ia32_pqr_assoc;
+
     uint64_t msr_fixed_ctr_ctrl;
     uint64_t msr_global_ctrl;
     uint64_t msr_global_status;
diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c
index 094aa56a20..e48e6b0da1 100644
--- a/target/i386/tcg/sysemu/misc_helper.c
+++ b/target/i386/tcg/sysemu/misc_helper.c
@@ -25,6 +25,7 @@
 #include "exec/address-spaces.h"
 #include "exec/exec-all.h"
 #include "tcg/helper-tcg.h"
+#include "hw/i386/rdt.h"
 #include "hw/i386/apic.h"
 
 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
@@ -293,6 +294,44 @@ void helper_wrmsr(CPUX86State *env)
         env->msr_bndcfgs = val;
         cpu_sync_bndcs_hflags(env);
         break;
+    case MSR_IA32_QM_EVTSEL:
+        env->msr_ia32_qm_evtsel = val;
+        break;
+    case MSR_IA32_PQR_ASSOC:
+    {
+        env->msr_ia32_pqr_assoc = val;
+        bool res = rdt_associate_rmid_cos(val);
+        if (!res)
+            goto error;
+        break;
+    }
+    case MSR_IA32_L3_CBM_BASE ... MSR_IA32_L3_MASKS_END:
+    {
+        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L3_CBM_BASE;
+        if (pos >= rdt_get_cpuid_10_1_edx_cos_max()) {
+            goto error;
+        }
+        rdt_write_msr_l3_mask(pos, val);
+        break;
+    }
+    case MSR_IA32_L2_CBM_BASE ... MSR_IA32_L2_CBM_END:
+    {
+        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_CBM_BASE;
+        if (pos >= rdt_get_cpuid_10_2_edx_cos_max()) {
+            goto error;
+        }
+        rdt_write_msr_l2_mask(pos, val);
+        break;
+    }
+    case MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE ... MSR_IA32_L2_QOS_Ext_BW_Thrtl_END:
+    {
+        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE;
+        if (pos >= rdt_get_cpuid_10_3_edx_cos_max()) {
+            goto error;
+        }
+        rdt_write_mba_thrtl(pos, val);
+        break;
+    }
     case MSR_APIC_START ... MSR_APIC_END: {
         int ret;
         int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
@@ -472,6 +511,44 @@ void helper_rdmsr(CPUX86State *env)
         val = (cs->nr_threads * cs->nr_cores) | (cs->nr_cores << 16);
         break;
     }
+    case MSR_IA32_QM_CTR:
+        val = rdt_read_event_count(x86_cpu->rdt,
+                                   (env->msr_ia32_qm_evtsel >> 32) & 0xff,
+                                   env->msr_ia32_qm_evtsel & 0xff);
+        break;
+    case MSR_IA32_QM_EVTSEL:
+        val = env->msr_ia32_qm_evtsel;
+        break;
+    case MSR_IA32_PQR_ASSOC:
+        val = env->msr_ia32_pqr_assoc;
+        break;
+    case MSR_IA32_L3_CBM_BASE ... MSR_IA32_L3_MASKS_END:
+    {
+        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L3_CBM_BASE;
+        if (pos >= rdt_get_cpuid_10_1_edx_cos_max()) {
+            goto error;
+        }
+        val = rdt_read_l3_mask(pos);
+        break;
+    }
+    case MSR_IA32_L2_CBM_BASE ... MSR_IA32_L2_CBM_END:
+    {
+        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_CBM_BASE;
+        if (pos >= rdt_get_cpuid_10_2_edx_cos_max()) {
+            goto error;
+        }
+        val = rdt_read_l2_mask(pos);
+        break;
+    }
+    case MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE ... MSR_IA32_L2_QOS_Ext_BW_Thrtl_END:
+    {
+        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE;
+        if (pos >= rdt_get_cpuid_10_3_edx_cos_max()) {
+            goto error;
+        }
+        val = rdt_read_mba_thrtl(pos);
+        break;
+    }
     case MSR_APIC_START ... MSR_APIC_END: {
         int ret;
         int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
@@ -499,6 +576,9 @@ void helper_rdmsr(CPUX86State *env)
     }
     env->regs[R_EAX] = (uint32_t)(val);
     env->regs[R_EDX] = (uint32_t)(val >> 32);
+return;
+error:
+    raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
 }
 
 void helper_flush_page(CPUX86State *env, target_ulong addr)
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 6/9] Add CPUID enumeration for RDT
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
                   ` (4 preceding siblings ...)
  2024-07-19 16:29 ` [PATCH v1 5/9] Add RDT device interface through MSRs Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-26 12:09   ` Jonathan Cameron via
  2024-07-19 16:29 ` [PATCH v1 7/9] Add RDT feature flags Hendrik Wuethrich
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Add CPUID enumeration for intel RDT monitoring and allocation, as well
as the flags used in the enumeration code.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 hw/i386/rdt.c         | 29 ++++++++++++++
 include/hw/i386/rdt.h | 29 ++++++++++++++
 target/i386/cpu.c     | 91 +++++++++++++++++++++++++++++++++++++++++++
 target/i386/cpu.h     |  5 +++
 4 files changed, 154 insertions(+)

diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
index 0d0e5751fc..5ad05f996a 100644
--- a/hw/i386/rdt.c
+++ b/hw/i386/rdt.c
@@ -17,8 +17,18 @@
 #define MAX_L2_MASK_COUNT      48
 #define MAX_MBA_THRTL_COUNT    31
 
+/* RDT L3 Allocation features */
+#define CPUID_10_1_EAX_CBM_LENGTH       0xf
+#define CPUID_10_1_EBX_CBM              0x0
+#define CPUID_10_1_ECX_CDP              0x0 // to enable, it would be (1U << 2)
 #define CPUID_10_1_EDX_COS_MAX          MAX_L3_MASK_COUNT
+/* RDT L2 Allocation features*/
+#define CPUID_10_2_EAX_CBM_LENGTH       0xf
+#define CPUID_10_2_EBX_CBM              0x0
 #define CPUID_10_2_EDX_COS_MAX          MAX_L2_MASK_COUNT
+/* RDT MBA features */
+#define CPUID_10_3_EAX_THRTL_MAX        89
+#define CPUID_10_3_ECX_LINEAR_RESPONSE (1U << 2)
 #define CPUID_10_3_EDX_COS_MAX          MAX_MBA_THRTL_COUNT
 
 #define TYPE_RDT "rdt"
@@ -61,8 +71,27 @@ struct RDTState {
 
 struct RDTStateClass { };
 
+uint32_t rdt_get_cpuid_15_0_edx_l3(void) { return CPUID_15_1_EDX_L3_OCCUPANCY | CPUID_15_1_EDX_L3_TOTAL_BW | CPUID_15_1_EDX_L3_LOCAL_BW; }
+
+uint32_t rdt_cpuid_15_1_edx_l3_total_bw_enabled(void) { return CPUID_15_1_EDX_L3_TOTAL_BW; }
+uint32_t rdt_cpuid_15_1_edx_l3_local_bw_enabled(void) { return CPUID_15_1_EDX_L3_LOCAL_BW; }
+uint32_t rdt_cpuid_15_1_edx_l3_occupancy_enabled(void) { return CPUID_15_1_EDX_L3_OCCUPANCY; }
+
+uint32_t rdt_cpuid_10_0_ebx_l3_cat_enabled(void) { return CPUID_10_0_EBX_L3_CAT; }
+uint32_t rdt_cpuid_10_0_ebx_l2_cat_enabled(void) { return CPUID_10_0_EBX_L2_CAT; }
+uint32_t rdt_cpuid_10_0_ebx_l2_mba_enabled(void) { return CPUID_10_0_EBX_MBA; }
+
+uint32_t rdt_get_cpuid_10_1_eax_cbm_length(void) { return CPUID_10_1_EAX_CBM_LENGTH; }
+uint32_t rdt_cpuid_10_1_ebx_cbm_enabled(void) { return CPUID_10_1_EBX_CBM; }
+uint32_t rdt_cpuid_10_1_ecx_cdp_enabled(void) { return CPUID_10_1_ECX_CDP; }
 uint32_t rdt_get_cpuid_10_1_edx_cos_max(void) { return CPUID_10_1_EDX_COS_MAX; }
+
+uint32_t rdt_get_cpuid_10_2_eax_cbm_length(void) { return CPUID_10_2_EAX_CBM_LENGTH; }
+uint32_t rdt_cpuid_10_2_ebx_cbm_enabled(void) { return CPUID_10_2_EBX_CBM; }
 uint32_t rdt_get_cpuid_10_2_edx_cos_max(void) { return CPUID_10_2_EDX_COS_MAX; }
+
+uint32_t rdt_get_cpuid_10_3_eax_thrtl_max(void) { return CPUID_10_3_EAX_THRTL_MAX; }
+uint32_t rdt_cpuid_10_3_eax_linear_response_enabled(void) { return CPUID_10_3_ECX_LINEAR_RESPONSE; }
 uint32_t rdt_get_cpuid_10_3_edx_cos_max(void) { return CPUID_10_3_EDX_COS_MAX; }
 
 bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
index 51d36822f0..74aba33995 100644
--- a/include/hw/i386/rdt.h
+++ b/include/hw/i386/rdt.h
@@ -4,15 +4,44 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+/* RDT L3 Cache Monitoring Technology */
+#define CPUID_15_0_EDX_L3               (1U << 1)
+#define CPUID_15_1_EDX_L3_OCCUPANCY     (1U << 0)
+#define CPUID_15_1_EDX_L3_TOTAL_BW      (1U << 1)
+#define CPUID_15_1_EDX_L3_LOCAL_BW      (1U << 2)
+
+/* RDT Cache Allocation Technology */
+#define CPUID_10_0_EBX_L3_CAT           (1U << 1)
+#define CPUID_10_0_EBX_L2_CAT           (1U << 2)
+#define CPUID_10_0_EBX_MBA              (1U << 3)
+#define CPUID_10_0_EDX CPUID_10_0_EBX_L3_CAT | CPUID_10_0_EBX_L2_CAT | CPUID_10_0_EBX_MBA
+
 typedef struct RDTState RDTState;
 typedef struct RDTStateInstance RDTStateInstance;
 typedef struct RDTMonitor RDTMonitor;
 typedef struct RDTAllocation RDTAllocation;
 
+uint32_t rdt_get_cpuid_15_0_edx_l3(void);
+
+uint32_t rdt_cpuid_15_1_edx_l3_total_bw_enabled(void);
+uint32_t rdt_cpuid_15_1_edx_l3_local_bw_enabled(void);
+uint32_t rdt_cpuid_15_1_edx_l3_occupancy_enabled(void);
+
+uint32_t rdt_cpuid_10_0_ebx_l3_cat_enabled(void);
+uint32_t rdt_cpuid_10_0_ebx_l2_cat_enabled(void);
+uint32_t rdt_cpuid_10_0_ebx_l2_mba_enabled(void);
+
+uint32_t rdt_get_cpuid_10_1_eax_cbm_length(void);
+uint32_t rdt_cpuid_10_1_ebx_cbm_enabled(void);
+uint32_t rdt_cpuid_10_1_ecx_cdp_enabled(void);
 uint32_t rdt_get_cpuid_10_1_edx_cos_max(void);
 
+uint32_t rdt_get_cpuid_10_2_eax_cbm_length(void);
+uint32_t rdt_cpuid_10_2_ebx_cbm_enabled(void);
 uint32_t rdt_get_cpuid_10_2_edx_cos_max(void);
 
+uint32_t rdt_get_cpuid_10_3_eax_thrtl_max(void);
+uint32_t rdt_cpuid_10_3_eax_linear_response_enabled(void);
 uint32_t rdt_get_cpuid_10_3_edx_cos_max(void);
 
 bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc);
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 4688d140c2..c61981bf82 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -42,6 +42,7 @@
 #include "hw/boards.h"
 #include "hw/i386/sgx-epc.h"
 #endif
+#include "hw/i386/rdt.h"
 
 #include "disas/capstone.h"
 #include "cpu-internal.h"
@@ -6629,6 +6630,96 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         assert(!(*eax & ~0x1f));
         *ebx &= 0xffff; /* The count doesn't need to be reliable. */
         break;
+#ifndef CONFIG_USER_ONLY
+    case 0xF:
+        /* Shared Resource Monitoring Enumeration Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_PQM))
+            break;
+        assert(cpu->rdt);
+        /* Non-zero count is ResId */
+        switch (count) {
+            /* Monitoring Resource Type Enumeration */
+            case 0:
+                *edx = env->features[FEAT_RDT_15_0_EDX];
+                *ebx = rdt_max_rmid(cpu->rdt);
+                break;
+            /* L3 Cache Monitoring Capability Enumeration Data */
+            case 1:
+                /* Upscaling Factor */
+                *ebx = 1;
+                /* MaxRMID */
+                *ecx = rdt_max_rmid(cpu->rdt);
+                /* Set L3 Total BW */
+                *edx |= rdt_cpuid_15_1_edx_l3_total_bw_enabled();
+                /* Set L3 Local BW */
+                *edx |= rdt_cpuid_15_1_edx_l3_local_bw_enabled();
+                /* Set L3 Occupancy */
+                *edx |= rdt_cpuid_15_1_edx_l3_occupancy_enabled();
+                break;
+            default:
+                break;
+        }
+        break;
+    case 0x10:
+        /* Shared Resource Director Technology Allocation Enumeration Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_PQE))
+            break;
+        assert(cpu->rdt);
+        /* Non-zero count is ResId */
+        switch (count) {
+            /* Cache Allocation Technology Available Resource Types */
+            case 0:
+                /* Set L3 CAT */
+                *ebx |= rdt_cpuid_10_0_ebx_l3_cat_enabled();
+                /* Set L2 CAT */
+                *ebx |= rdt_cpuid_10_0_ebx_l2_cat_enabled();
+                /* Set MBA */
+                *ebx |= rdt_cpuid_10_0_ebx_l2_mba_enabled();
+                // *edx = env->features[FEAT_RDT_10_0_EBX];
+                break;
+            case 1:
+                /* Length of capacity bitmask in -1 notation */
+                *eax = rdt_get_cpuid_10_1_eax_cbm_length();
+                /* Capability bit mask */
+                *ebx = rdt_cpuid_10_1_ebx_cbm_enabled();
+                /* Code and Data priotitization */
+                *ecx |= rdt_cpuid_10_1_ecx_cdp_enabled();
+                /* Support for n COS masks (zero-referenced)*/
+                *edx =  rdt_get_cpuid_10_1_edx_cos_max();
+                break;
+            case 2:
+                /* Length of capacity bitmask in -1 notation */
+                *eax = rdt_get_cpuid_10_2_eax_cbm_length();
+                /* Capability bit mask */
+                *ebx = rdt_cpuid_10_2_ebx_cbm_enabled();
+                /* Support for n COS masks (zero-referenced)*/
+                *edx =  rdt_get_cpuid_10_2_edx_cos_max();
+                break;
+            case 3:
+                /* Max throttling value -1 (89 means 90) */
+                *eax = rdt_get_cpuid_10_3_eax_thrtl_max();
+                /* Linear response of delay values */
+                *ecx = rdt_cpuid_10_3_eax_linear_response_enabled();
+                /* Max number of CLOS -1 (15 means 16) */
+                *edx = rdt_get_cpuid_10_3_edx_cos_max();
+                break;
+            default:
+                *eax = 0;
+                *ebx = 0;
+                *ecx = 0;
+                *edx = 0;
+                break;
+        }
+        break;
+#endif
     case 0x1C:
         if (cpu->enable_pmu && (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
             x86_cpu_get_supported_cpuid(0x1C, 0, eax, ebx, ecx, edx);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 0b3aca2d02..12a4b989af 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -673,6 +673,7 @@ typedef enum FeatureWord {
     FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
     FEAT_7_1_EDX,       /* CPUID[EAX=7,ECX=1].EDX */
     FEAT_7_2_EDX,       /* CPUID[EAX=7,ECX=2].EDX */
+    FEAT_RDT_15_0_EDX,  /* CPUID[EAX=0xf,ECX=0].EDX (RDT CMT/MBM) */
     FEATURE_WORDS,
 } FeatureWord;
 
@@ -843,8 +844,12 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
 #define CPUID_7_0_EBX_INVPCID           (1U << 10)
 /* Restricted Transactional Memory */
 #define CPUID_7_0_EBX_RTM               (1U << 11)
+/* Resource Director Technology Monitoring */
+#define CPUID_7_0_EBX_PQM               (1U << 12)
 /* Memory Protection Extension */
 #define CPUID_7_0_EBX_MPX               (1U << 14)
+/* Resource Director Technology Allocation */
+#define CPUID_7_0_EBX_PQE               (1U << 15)
 /* AVX-512 Foundation */
 #define CPUID_7_0_EBX_AVX512F           (1U << 16)
 /* AVX-512 Doubleword & Quadword Instruction */
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 7/9] Add RDT feature flags.
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
                   ` (5 preceding siblings ...)
  2024-07-19 16:29 ` [PATCH v1 6/9] Add CPUID enumeration for RDT Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 8/9] Adjust CPUID level for RDT features Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 9/9] Adjust level for RDT on full_cpuid_auto_level Hendrik Wuethrich
  8 siblings, 0 replies; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Add RDT features to feature word / TCG.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 target/i386/cpu.c | 30 ++++++++++++++++++++++++++++--
 target/i386/cpu.h |  2 ++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index c61981bf82..1cf5e5d5ff 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -864,7 +864,8 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
           CPUID_7_0_EBX_CLFLUSHOPT |            \
           CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \
           CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_RDSEED | \
-          CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_KERNEL_FEATURES)
+          CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_KERNEL_FEATURES | \
+          CPUID_7_0_EBX_PQM | CPUID_7_0_EBX_PQE)
           /* missing:
           CPUID_7_0_EBX_HLE
           CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
@@ -900,6 +901,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
 #define TCG_SGX_12_0_EAX_FEATURES 0
 #define TCG_SGX_12_0_EBX_FEATURES 0
 #define TCG_SGX_12_1_EAX_FEATURES 0
+#define TCG_RDT_15_0_EDX_FEATURES CPUID_15_0_EDX_L3
 
 #if defined CONFIG_USER_ONLY
 #define CPUID_8000_0008_EBX_KERNEL_FEATURES (CPUID_8000_0008_EBX_IBPB | \
@@ -1057,7 +1059,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             "fsgsbase", "tsc-adjust", "sgx", "bmi1",
             "hle", "avx2", NULL, "smep",
             "bmi2", "erms", "invpcid", "rtm",
-            NULL, NULL, "mpx", NULL,
+            "rdt-m", NULL, "mpx", "rdt-a",
             "avx512f", "avx512dq", "rdseed", "adx",
             "smap", "avx512ifma", "pcommit", "clflushopt",
             "clwb", "intel-pt", "avx512pf", "avx512er",
@@ -1607,6 +1609,30 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         },
         .tcg_features = TCG_SGX_12_1_EAX_FEATURES,
     },
+
+    [FEAT_RDT_10_0_EBX] = {
+        .type = CPUID_FEATURE_WORD,
+        .feat_names = {
+            NULL, "l3-cat", "l2-cat", "mba"
+        },
+        .cpuid = {
+            .eax = 0x10,
+            .needs_ecx = true, .ecx = 0,
+            .reg = R_EBX,
+        }
+    },
+    [FEAT_RDT_15_0_EDX] = {
+        .type = CPUID_FEATURE_WORD,
+        .feat_names = {
+            [1] = "l3-cmt"
+        },
+        .cpuid = {
+            .eax = 0xf,
+            .needs_ecx = true, .ecx = 0,
+            .reg = R_EDX,
+        },
+        .tcg_features = TCG_RDT_15_0_EDX_FEATURES,
+    },
 };
 
 typedef struct FeatureMask {
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 12a4b989af..bf2f3c07a7 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -673,7 +673,9 @@ typedef enum FeatureWord {
     FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
     FEAT_7_1_EDX,       /* CPUID[EAX=7,ECX=1].EDX */
     FEAT_7_2_EDX,       /* CPUID[EAX=7,ECX=2].EDX */
+    FEAT_RDT_15_0_EBX,  /* CPUID[EAX=0xf,ECX=0].EBX (RDT CMT/MBM) */
     FEAT_RDT_15_0_EDX,  /* CPUID[EAX=0xf,ECX=0].EDX (RDT CMT/MBM) */
+    FEAT_RDT_10_0_EBX,  /* CPUID[EAX=0x10,ECX=0].EBX (RDT CAT/MBA) */
     FEATURE_WORDS,
 } FeatureWord;
 
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 8/9] Adjust CPUID level for RDT features
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
                   ` (6 preceding siblings ...)
  2024-07-19 16:29 ` [PATCH v1 7/9] Add RDT feature flags Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  2024-07-19 16:29 ` [PATCH v1 9/9] Adjust level for RDT on full_cpuid_auto_level Hendrik Wuethrich
  8 siblings, 0 replies; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Adjust minimum CPUID level if RDT monitoring or allocation features are
enabled to ensure that CPUID will return them.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 target/i386/cpu.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1cf5e5d5ff..482f980a1f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7590,6 +7590,16 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
         if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SGX) {
             x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x12);
         }
+
+        /* RDT monitoring requires CPUID[0xF] */
+        if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_PQM) {
+            x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0xF);
+        }
+
+        /* RDT allocation requires CPUID[0x10] */
+        if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_PQE) {
+            x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x10);
+        }
     }
 
     /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v1 9/9] Adjust level for RDT on full_cpuid_auto_level
  2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
                   ` (7 preceding siblings ...)
  2024-07-19 16:29 ` [PATCH v1 8/9] Adjust CPUID level for RDT features Hendrik Wuethrich
@ 2024-07-19 16:29 ` Hendrik Wuethrich
  8 siblings, 0 replies; 18+ messages in thread
From: Hendrik Wuethrich @ 2024-07-19 16:29 UTC (permalink / raw)
  To: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini
  Cc: peternewman, ‪Hendrik Wüthrich

From: ‪Hendrik Wüthrich <whendrik@google.com>

Make sure that RDT monitoring and allocation features are included in
in full_cpuid_auto_level.

Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
---
 target/i386/cpu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 482f980a1f..6f5594d3e2 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -875,6 +875,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
 #else
 #define TCG_7_0_ECX_RDPID 0
 #endif
+
 #define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | \
           /* CPUID_7_0_ECX_OSPKE is dynamic */ \
           CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES | \
@@ -7548,6 +7549,8 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
         x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
         x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
         x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
+        x86_cpu_adjust_feat_level(cpu, FEAT_RDT_15_0_EDX);
+        x86_cpu_adjust_feat_level(cpu, FEAT_RDT_10_0_EBX);
 
         /* Intel Processor Trace requires CPUID[0x14] */
         if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT)) {
-- 
2.45.2.1089.g2a221341d9-goog



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 1/9] Add Intel RDT device to config.
  2024-07-19 16:29 ` [PATCH v1 1/9] Add Intel RDT device to config Hendrik Wuethrich
@ 2024-07-26 10:24   ` Jonathan Cameron via
  2024-09-04 14:14     ` Hendrik Wüthrich
  0 siblings, 1 reply; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 10:24 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:21 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <whendrik@google.com>
> 
> Change config to show RDT, add minimal code to the rdt.c module to make
> sure things still compile.
> 
> Signed-off-by: Hendrik Wüthrich <whendrik@google.com>

Hi Hendrik

Great to see emulation of this. Will be handy for testing
kernel changes etc.

Not convinced it's worth a separate patch just to add stubs.
Why not at least bring some real code in with this?

> ---
>  hw/i386/Kconfig       |  4 ++++
>  hw/i386/meson.build   |  1 +
>  hw/i386/rdt.c         | 49 +++++++++++++++++++++++++++++++++++++++++++
>  include/hw/i386/rdt.h | 12 +++++++++++
>  4 files changed, 66 insertions(+)
>  create mode 100644 hw/i386/rdt.c
>  create mode 100644 include/hw/i386/rdt.h
> 
> diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
> index f4a33b6c08..4dd05ed6f2 100644
> --- a/hw/i386/Kconfig
> +++ b/hw/i386/Kconfig
> @@ -10,6 +10,9 @@ config SGX
>      bool
>      depends on KVM
>  
> +config RDT
> +    bool
> +
>  config PC
>      bool
>      imply APPLESMC
> @@ -26,6 +29,7 @@ config PC
>      imply QXL
>      imply SEV
>      imply SGX
> +    imply RDT
>      imply TEST_DEVICES
>      imply TPM_CRB
>      imply TPM_TIS_ISA
> diff --git a/hw/i386/meson.build b/hw/i386/meson.build
> index 03aad10df7..fdbf5962b5 100644
> --- a/hw/i386/meson.build
> +++ b/hw/i386/meson.build
> @@ -21,6 +21,7 @@ i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
>  i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c'))
>  i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c','sgx.c'),
>                                  if_false: files('sgx-stub.c'))
> +i386_ss.add(when: 'CONFIG_RDT', if_true: files('rdt.c'))
>  
>  i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
>  i386_ss.add(when: 'CONFIG_PC', if_true: files(
> diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> new file mode 100644
> index 0000000000..0a5e95606b
> --- /dev/null
> +++ b/hw/i386/rdt.c

License etc missing.

> @@ -0,0 +1,49 @@
> +#include "qemu/osdep.h"
> +#include "hw/i386/rdt.h"
> +#include <stdint.h>
> +#include "hw/qdev-properties.h"
> +#include "qemu/typedefs.h"
> +#include "qom/object.h"
> +#include "target/i386/cpu.h"
> +#include "hw/isa/isa.h"

Ordering seems a bit random.  I don't really mind what order
they are in but it is easier to pick an option so it
becomes obvious where to put things later.

Also better to bring these in when they are needed so it
is obvious why they are here.


> +
> +#define TYPE_RDT "rdt"
> +
> +OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
> +
> +struct RDTState {
> +    ISADevice parent;
> +};
> +
> +struct RDTStateClass { };
I'd do
...Class {
};

As will reduce noise in later patches assuming this will have
content.


> +
> +OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
> +
> +static Property rdt_properties[] = {
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void rdt_init(Object *obj)

Not used?

> +{
> +}
> +
> +static void rdt_realize(DeviceState *dev, Error **errp)
> +{
> +}
> +
> +static void rdt_finalize(Object *obj)
> +{
> +}

Not used?

> +
> +static void rdt_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->hotpluggable = false;
> +    dc->desc = "RDT";
> +    dc->user_creatable = true;
> +    dc->realize = rdt_realize;
> +
> +    device_class_set_props(dc, rdt_properties);
> +}
> +
> diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
> new file mode 100644
> index 0000000000..45e34d3103
> --- /dev/null
> +++ b/include/hw/i386/rdt.h
> @@ -0,0 +1,12 @@
> +#ifndef HW_RDT_H
> +#define HW_RDT_H
> +
> +#include <stdbool.h>
> +#include <stdint.h>

Not used so don't include them until needed.

> +
> +typedef struct RDTState RDTState;
> +typedef struct RDTStateInstance RDTStateInstance;
> +typedef struct RDTMonitor RDTMonitor;
> +typedef struct RDTAllocation RDTAllocation;
> +
> +#endif



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 2/9] Add state for RDT device.
  2024-07-19 16:29 ` [PATCH v1 2/9] Add state for RDT device Hendrik Wuethrich
@ 2024-07-26 10:33   ` Jonathan Cameron via
  0 siblings, 0 replies; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 10:33 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:22 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <whendrik@google.com>
> 
> Add structures and variables needed to emulate Intel RDT, including
> module-internal sturctures and state in ArchCPU. No functionality yet.
> 
> Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
A few general comments inline.

J
> ---
>  hw/i386/rdt.c     | 33 +++++++++++++++++++++++++++++++++
>  target/i386/cpu.h |  5 +++++
>  2 files changed, 38 insertions(+)
> 
> diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> index 0a5e95606b..cf246ab835 100644
> --- a/hw/i386/rdt.c
> +++ b/hw/i386/rdt.c
> @@ -7,12 +7,44 @@
>  #include "target/i386/cpu.h"
>  #include "hw/isa/isa.h"
>  
> +/* Max counts for allocation masks or CBMs. In other words, the size of respective MSRs*/
> +#define MAX_L3_MASK_COUNT      128

If these are an architectural limitation rather than a qemu one good
to have a reference. If it's an RDT requirement namespace them with
RDT_*

> +#define MAX_L2_MASK_COUNT      48
> +#define MAX_MBA_THRTL_COUNT    31
> +
>  #define TYPE_RDT "rdt"
> +#define RDT_NUM_RMID_PROP "rmids"
>  
>  OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
>  
> +struct RDTMonitor {
> +    uint64_t count_local;
> +    uint64_t count_remote;
> +    uint64_t count_l3;
> +};
> +
> +struct RDTAllocation {
> +    uint32_t active_cos;
> +};
> +
> +struct RDTStateInstance {

I'd add some docs for this and RDTState to make it obvious
what the scope of each is.  What do they represent and how
is it different?
This seems like it might be the per core part.  If so can
you name it to make that obvious?  RDTPerCoreState or
something like that?

> +    uint32_t active_rmid;
> +    GArray *monitors;
> +
> +    RDTState *rdtstate;
> +};
> +
>  struct RDTState {
>      ISADevice parent;
> +
> +    uint32_t rmids;
> +
> +    GArray *rdtInstances;

Whilst naming makes it likely I'd add a comment to say this
an array of RDTStateInstance with (I think) one per core?

> +    GArray *allocations;
> +
> +    uint32_t msr_L3_ia32_mask_n[MAX_L3_MASK_COUNT];
> +    uint32_t msr_L2_ia32_mask_n[MAX_L2_MASK_COUNT];
> +    uint32_t ia32_L2_qos_ext_bw_thrtl_n[MAX_MBA_THRTL_COUNT];
>  };
>  
>  struct RDTStateClass { };
> @@ -20,6 +52,7 @@ struct RDTStateClass { };
>  OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
>  
>  static Property rdt_properties[] = {
> +    DEFINE_PROP_UINT32(RDT_NUM_RMID_PROP, RDTState, rmids, 256),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 1e121acef5..bd0bbb75f2 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1987,6 +1987,8 @@ typedef struct CPUArchState {
>  
>  struct kvm_msrs;
>  
> +struct RDTState;

Not used?

> +struct rdtStateInstance;
>  /**
>   * X86CPU:
>   * @env: #CPUX86State
> @@ -2143,6 +2145,9 @@ struct ArchCPU {
>      struct MemoryRegion *cpu_as_root, *cpu_as_mem, *smram;
>      Notifier machine_done;
>  
> +    /* Help the RDT MSRs find the RDT device */
> +    struct RDTStateInstance *rdt;
> +
>      struct kvm_msrs *kvm_msr_buf;
>  
>      int32_t node_id; /* NUMA node this CPU belongs to */



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 3/9] Add init and realize funciontality for RDT device.
  2024-07-19 16:29 ` [PATCH v1 3/9] Add init and realize funciontality " Hendrik Wuethrich
@ 2024-07-26 10:41   ` Jonathan Cameron via
  2024-07-26 10:42   ` Jonathan Cameron via
  1 sibling, 0 replies; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 10:41 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:23 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <whendrik@google.com>
> 
> Add code to initialize all necessary state for the RDT device.
> 
> Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
> ---
>  hw/i386/rdt.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> index cf246ab835..259dafc963 100644
> --- a/hw/i386/rdt.c
> +++ b/hw/i386/rdt.c
> @@ -62,10 +62,38 @@ static void rdt_init(Object *obj)
>  
>  static void rdt_realize(DeviceState *dev, Error **errp)
>  {
> +    CPUState *cs = first_cpu;
> +

No blank line here.

> +    RDTState *rdtDev = RDT(dev);

blank line here.

> +    rdtDev->rdtInstances = g_array_new(false, true, sizeof(RDTStateInstance));
> +    g_array_set_size(rdtDev->rdtInstances, cs->nr_cores);
> +    CPU_FOREACH(cs) {
> +        RDTStateInstance *rdt = &g_array_index(rdtDev->rdtInstances, RDTStateInstance, cs->cpu_index);
> +
No blank line here. Also wrap this long line somewhere.

> +        X86CPU *cpu = X86_CPU(cs);
blank line here.

> +        rdt->rdtstate = rdtDev;
> +        cpu->rdt = rdt;
> +
> +        rdt->monitors = g_array_new(false, true, sizeof(RDTMonitor));
> +        rdt->rdtstate->allocations = g_array_new(false, true, sizeof(RDTAllocation));
> +
> +        g_array_set_size(rdt->monitors, rdtDev->rmids);
> +        g_array_set_size(rdt->rdtstate->allocations, rdtDev->rmids);

Are these g_array's going to change size? If not, why go through this dance when
a simple pointer will do?


> +    }
>  }
>  
>  static void rdt_finalize(Object *obj)
>  {
> +    CPUState *cs;
> +    RDTState *rdt = RDT(obj);
> +
> +    CPU_FOREACH(cs) {
> +        RDTStateInstance *rdtInstance = &g_array_index(rdt->rdtInstances, RDTStateInstance, cs->cpu_index);

Long line. Wrap that.  Worth running checkpatch which I think
will moan about things like this.



> +        g_array_free(rdtInstance->monitors, true);
> +        g_array_free(rdtInstance->rdtstate->allocations, true);
> +    }
> +
> +    g_array_free(rdt->rdtInstances, true);
>  }
>  
>  static void rdt_class_init(ObjectClass *klass, void *data)



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 3/9] Add init and realize funciontality for RDT device.
  2024-07-19 16:29 ` [PATCH v1 3/9] Add init and realize funciontality " Hendrik Wuethrich
  2024-07-26 10:41   ` Jonathan Cameron via
@ 2024-07-26 10:42   ` Jonathan Cameron via
  1 sibling, 0 replies; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 10:42 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:23 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <whendrik@google.com>
> 
> Add code to initialize all necessary state for the RDT device.
> 
> Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
Spell check (typo in patch title).


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 4/9] Add RDT functionality
  2024-07-19 16:29 ` [PATCH v1 4/9] Add RDT functionality Hendrik Wuethrich
@ 2024-07-26 10:51   ` Jonathan Cameron via
  0 siblings, 0 replies; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 10:51 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:24 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <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 Wüthrich <whendrik@google.com>
> ---
>  hw/i386/rdt.c         | 124 ++++++++++++++++++++++++++++++++++++++++++
>  include/hw/i386/rdt.h |  13 +++++
>  2 files changed, 137 insertions(+)
> 
> diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> index 259dafc963..77b7b4f2d4 100644
> --- a/hw/i386/rdt.c
> +++ b/hw/i386/rdt.c
> @@ -7,6 +7,11 @@
>  #include "target/i386/cpu.h"
>  #include "hw/isa/isa.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 MAX_L3_MASK_COUNT      128
>  #define MAX_L2_MASK_COUNT      48
> @@ -15,6 +20,9 @@
>  #define TYPE_RDT "rdt"
>  #define RDT_NUM_RMID_PROP "rmids"
>  
> +#define QM_CTR_Error        (1ULL << 63)
> +#define QM_CTR_Unavailable  (1ULL << 62)

Mix of capitals and camel case is a bit unusual. I'd go
capitals throughout unless there is precedence.

Also, prefix with RDT_QM probably so we know it's a local
define where it is used.

> +
>  OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
>  
>  struct RDTMonitor {
> @@ -49,6 +57,122 @@ struct RDTState {
>  
>  struct RDTStateClass { };
>  
> +bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
> +    X86CPU *cpu = X86_CPU(current_cpu);
> +    RDTStateInstance *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 > MAX_L3_MASK_COUNT || cos_id > MAX_L2_MASK_COUNT ||
> +    cos_id > MAX_MBA_THRTL_COUNT || rmid > rdt_max_rmid(rdt)) {

Fix indent to be
       if (cos_id...
           cos_id > ...


> +        return false;
> +    }
> +
> +    rdt->active_rmid = rmid;
> +
> +    alloc = &g_array_index(rdt->rdtstate->allocations, RDTAllocation, rmid);
> +
> +    alloc->active_cos = cos_id;
> +
> +    return true;
> +}
> +
> +uint32_t rdt_read_l3_mask(uint32_t pos)
> +{
> +    X86CPU *cpu = X86_CPU(current_cpu);
> +    RDTStateInstance *rdt = cpu->rdt;
> +
> +    uint32_t val = rdt->rdtstate->msr_L3_ia32_mask_n[pos];
> +    return val;

return rdt->

> +}
> +
> +uint32_t rdt_read_l2_mask(uint32_t pos)
> +{
> +    X86CPU *cpu = X86_CPU(current_cpu);
> +    RDTStateInstance *rdt = cpu->rdt;
> +
> +    uint32_t val = rdt->rdtstate->msr_L2_ia32_mask_n[pos];
> +    return val;

return rdt->

> +}
> +
> +uint32_t rdt_read_mba_thrtl(uint32_t pos)
> +{
> +    X86CPU *cpu = X86_CPU(current_cpu);
> +    RDTStateInstance *rdt = cpu->rdt;
> +
> +    uint32_t val = rdt->rdtstate->ia32_L2_qos_ext_bw_thrtl_n[pos];
> +    return val;

return rdt->rdstate...

> +}
> +
> +void rdt_write_msr_l3_mask(uint32_t pos, uint32_t val) {
> +    X86CPU *cpu = X86_CPU(current_cpu);
> +    RDTStateInstance *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);
> +    RDTStateInstance *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);
> +    RDTStateInstance *rdt = cpu->rdt;
> +
> +    rdt->rdtstate->ia32_L2_qos_ext_bw_thrtl_n[pos] = val;
> +}
> +
> +uint32_t rdt_max_rmid(RDTStateInstance *rdt)
> +{
> +    RDTState *rdtdev = rdt->rdtstate;
> +    return rdtdev->rmids - 1;
> +}
> +
> +uint64_t rdt_read_event_count(RDTStateInstance *rdtInstance, uint32_t rmid, uint32_t event_id)

Long line - consider wrapping it.

> +{
> +    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 = &g_array_index(rdt->rdtInstances, RDTStateInstance, 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;

break after return not needed. I'm a bit surprised that didn't give you a warning.


> +        default:
> +            return QM_CTR_Error;
> +    }
> +}
> +
>  OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
>  
>  static Property rdt_properties[] = {
> diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
> index 45e34d3103..8092c5f290 100644
> --- a/include/hw/i386/rdt.h
> +++ b/include/hw/i386/rdt.h
> @@ -10,3 +10,16 @@ typedef struct RDTMonitor RDTMonitor;
>  typedef struct RDTAllocation RDTAllocation;
>  
>  #endif
> +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(RDTStateInstance *rdt, uint32_t rmid, uint32_t event_id);
> +uint32_t rdt_max_rmid(RDTStateInstance *rdt);
> +
Trailing blank line doesn't add anything so I'd drop it.

Jonathan


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 5/9] Add RDT device interface through MSRs
  2024-07-19 16:29 ` [PATCH v1 5/9] Add RDT device interface through MSRs Hendrik Wuethrich
@ 2024-07-26 10:57   ` Jonathan Cameron via
  0 siblings, 0 replies; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 10:57 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:25 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <whendrik@google.com>
> 
> Implement rdmsr and wrmsr for the following MSRs:
> * MSR_IA32_PQR_ASSOC
> * MSR_IA32_QM_EVTSEL
> * MSR_IA32_QM_CTR
> * IA32_L3_QOS_Mask_n
> * IA32_L2_QOS_Mask_n
> * IA32_L2_QoS_Ext_BW_Thrtl_n
> 
> This allows for the guest to call RDT-internal functions to
> associate an RMID with a CLOSID / set an active RMID for
> monitoring, read monitoring data, and set classes of service.
> 
> Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
A few comments inline. Mostly code cleanup stuff.

> ---
>  hw/i386/rdt.c                        |  8 +++
>  include/hw/i386/rdt.h                |  8 ++-
>  target/i386/cpu.h                    | 14 +++++
>  target/i386/tcg/sysemu/misc_helper.c | 80 ++++++++++++++++++++++++++++
>  4 files changed, 109 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> index 77b7b4f2d4..0d0e5751fc 100644
> --- a/hw/i386/rdt.c
> +++ b/hw/i386/rdt.c
> @@ -17,6 +17,10 @@
>  #define MAX_L2_MASK_COUNT      48
>  #define MAX_MBA_THRTL_COUNT    31
>  
> +#define CPUID_10_1_EDX_COS_MAX          MAX_L3_MASK_COUNT
> +#define CPUID_10_2_EDX_COS_MAX          MAX_L2_MASK_COUNT
> +#define CPUID_10_3_EDX_COS_MAX          MAX_MBA_THRTL_COUNT

Worth these defines?  Seems easier to just use the MAX_L3...
etc

> +
>  #define TYPE_RDT "rdt"
>  #define RDT_NUM_RMID_PROP "rmids"
>  
> @@ -57,6 +61,10 @@ struct RDTState {
>  
>  struct RDTStateClass { };
>  
> +uint32_t rdt_get_cpuid_10_1_edx_cos_max(void) { return CPUID_10_1_EDX_COS_MAX; }
> +uint32_t rdt_get_cpuid_10_2_edx_cos_max(void) { return CPUID_10_2_EDX_COS_MAX; }
> +uint32_t rdt_get_cpuid_10_3_edx_cos_max(void) { return CPUID_10_3_EDX_COS_MAX; }
> +
>  bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
>      X86CPU *cpu = X86_CPU(current_cpu);
>      RDTStateInstance *rdt = cpu->rdt;
> diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
> index 8092c5f290..51d36822f0 100644
> --- a/include/hw/i386/rdt.h
> +++ b/include/hw/i386/rdt.h
> @@ -9,7 +9,12 @@ typedef struct RDTStateInstance RDTStateInstance;
>  typedef struct RDTMonitor RDTMonitor;
>  typedef struct RDTAllocation RDTAllocation;
>  
> -#endif
> +uint32_t rdt_get_cpuid_10_1_edx_cos_max(void);
> +
> +uint32_t rdt_get_cpuid_10_2_edx_cos_max(void);
> +
> +uint32_t rdt_get_cpuid_10_3_edx_cos_max(void);

No need for blank lines between these related function
definitions.

> +
>  bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc);
>  
>  void rdt_write_msr_l3_mask(uint32_t pos, uint32_t val);
> @@ -23,3 +28,4 @@ uint32_t rdt_read_mba_thrtl(uint32_t pos);
>  uint64_t rdt_read_event_count(RDTStateInstance *rdt, uint32_t rmid, uint32_t event_id);
>  uint32_t rdt_max_rmid(RDTStateInstance *rdt);
>  
> +#endif

Fix that in earlier patch not here.

> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index bd0bbb75f2..0b3aca2d02 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -574,6 +574,17 @@ typedef enum X86Seg {
>  #define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
>  #define MSR_IA32_VMX_VMFUNC             0x00000491
>  
> +#define MSR_IA32_QM_EVTSEL                  0x0c8d
> +#define MSR_IA32_QM_CTR                     0x0c8e
> +#define MSR_IA32_PQR_ASSOC                  0x0c8f
> +
> +#define MSR_IA32_L3_CBM_BASE                0x0c90
> +#define MSR_IA32_L3_MASKS_END               0x0d0f
> +#define MSR_IA32_L2_CBM_BASE                0x0d10
> +#define MSR_IA32_L2_CBM_END                 0x0d4f
> +#define MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE   0xd50
> +#define MSR_IA32_L2_QOS_Ext_BW_Thrtl_END    0xd80
> +
>  #define MSR_APIC_START                  0x00000800
>  #define MSR_APIC_END                    0x000008ff
>  
> @@ -1778,6 +1789,9 @@ typedef struct CPUArchState {
>      uint64_t msr_ia32_feature_control;
>      uint64_t msr_ia32_sgxlepubkeyhash[4];
>  
> +    uint64_t msr_ia32_qm_evtsel;
> +    uint64_t msr_ia32_pqr_assoc;
> +
>      uint64_t msr_fixed_ctr_ctrl;
>      uint64_t msr_global_ctrl;
>      uint64_t msr_global_status;
> diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c
> index 094aa56a20..e48e6b0da1 100644
> --- a/target/i386/tcg/sysemu/misc_helper.c
> +++ b/target/i386/tcg/sysemu/misc_helper.c
> @@ -25,6 +25,7 @@
>  #include "exec/address-spaces.h"
>  #include "exec/exec-all.h"
>  #include "tcg/helper-tcg.h"
> +#include "hw/i386/rdt.h"
>  #include "hw/i386/apic.h"
>  
>  void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
> @@ -293,6 +294,44 @@ void helper_wrmsr(CPUX86State *env)
>          env->msr_bndcfgs = val;
>          cpu_sync_bndcs_hflags(env);
>          break;
> +    case MSR_IA32_QM_EVTSEL:
> +        env->msr_ia32_qm_evtsel = val;
> +        break;
> +    case MSR_IA32_PQR_ASSOC:
> +    {
> +        env->msr_ia32_pqr_assoc = val;
> +        bool res = rdt_associate_rmid_cos(val);
QEMU tends to use traditional C style, so declare
variables at start of scope then blank line.
However...

> +        if (!res)
> +            goto error;
           if (rdt_associate_rmid_cos(val)) {
               goto error;
           }
> +        break;
> +    }
Drop this scoping as bool will have gone away.

> +    case MSR_IA32_L3_CBM_BASE ... MSR_IA32_L3_MASKS_END:
> +    {
> +        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L3_CBM_BASE;
blank line

> +        if (pos >= rdt_get_cpuid_10_1_edx_cos_max()) {
> +            goto error;
> +        }
> +        rdt_write_msr_l3_mask(pos, val);
> +        break;
> +    }
> +    case MSR_IA32_L2_CBM_BASE ... MSR_IA32_L2_CBM_END:
> +    {
> +        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_CBM_BASE;
blank line.
> +        if (pos >= rdt_get_cpuid_10_2_edx_cos_max()) {
> +            goto error;
> +        }
> +        rdt_write_msr_l2_mask(pos, val);
> +        break;
> +    }
> +    case MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE ... MSR_IA32_L2_QOS_Ext_BW_Thrtl_END:
> +    {
> +        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE;

blank line

> +        if (pos >= rdt_get_cpuid_10_3_edx_cos_max()) {
> +            goto error;
> +        }
> +        rdt_write_mba_thrtl(pos, val);
> +        break;
> +    }
>      case MSR_APIC_START ... MSR_APIC_END: {
>          int ret;
>          int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
> @@ -472,6 +511,44 @@ void helper_rdmsr(CPUX86State *env)
>          val = (cs->nr_threads * cs->nr_cores) | (cs->nr_cores << 16);
>          break;
>      }
> +    case MSR_IA32_QM_CTR:
> +        val = rdt_read_event_count(x86_cpu->rdt,
> +                                   (env->msr_ia32_qm_evtsel >> 32) & 0xff,
> +                                   env->msr_ia32_qm_evtsel & 0xff);
> +        break;
> +    case MSR_IA32_QM_EVTSEL:
> +        val = env->msr_ia32_qm_evtsel;
> +        break;
> +    case MSR_IA32_PQR_ASSOC:
> +        val = env->msr_ia32_pqr_assoc;
> +        break;
> +    case MSR_IA32_L3_CBM_BASE ... MSR_IA32_L3_MASKS_END:
> +    {
> +        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L3_CBM_BASE;

blank line.

> +        if (pos >= rdt_get_cpuid_10_1_edx_cos_max()) {
> +            goto error;
> +        }
> +        val = rdt_read_l3_mask(pos);
> +        break;
> +    }
> +    case MSR_IA32_L2_CBM_BASE ... MSR_IA32_L2_CBM_END:
> +    {
> +        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_CBM_BASE;

blank line.

> +        if (pos >= rdt_get_cpuid_10_2_edx_cos_max()) {
> +            goto error;
> +        }
> +        val = rdt_read_l2_mask(pos);
> +        break;
> +    }
> +    case MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE ... MSR_IA32_L2_QOS_Ext_BW_Thrtl_END:
> +    {
> +        uint32_t pos = (uint32_t)env->regs[R_ECX] - MSR_IA32_L2_QOS_Ext_BW_Thrtl_BASE;

blank line.

> +        if (pos >= rdt_get_cpuid_10_3_edx_cos_max()) {
> +            goto error;
> +        }
> +        val = rdt_read_mba_thrtl(pos);
> +        break;
> +    }
>      case MSR_APIC_START ... MSR_APIC_END: {
>          int ret;
>          int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
> @@ -499,6 +576,9 @@ void helper_rdmsr(CPUX86State *env)
>      }
>      env->regs[R_EAX] = (uint32_t)(val);
>      env->regs[R_EDX] = (uint32_t)(val >> 32);
> +return;
    return;
fix the indent

blank line after the return.

> +error:
> +    raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
If this is only thing to do in error path it might be easier
to just do that inline instead of goto.

>  }
>  
>  void helper_flush_page(CPUX86State *env, target_ulong addr)



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 6/9] Add CPUID enumeration for RDT
  2024-07-19 16:29 ` [PATCH v1 6/9] Add CPUID enumeration for RDT Hendrik Wuethrich
@ 2024-07-26 12:09   ` Jonathan Cameron via
  0 siblings, 0 replies; 18+ messages in thread
From: Jonathan Cameron via @ 2024-07-26 12:09 UTC (permalink / raw)
  To: Hendrik Wuethrich
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, 19 Jul 2024 16:29:26 +0000
Hendrik Wuethrich <whendrik@google.com> wrote:

> From: ‪Hendrik Wüthrich <whendrik@google.com>
> 
> Add CPUID enumeration for intel RDT monitoring and allocation, as well
> as the flags used in the enumeration code.
> 
> Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
> ---
>  hw/i386/rdt.c         | 29 ++++++++++++++
>  include/hw/i386/rdt.h | 29 ++++++++++++++
>  target/i386/cpu.c     | 91 +++++++++++++++++++++++++++++++++++++++++++
>  target/i386/cpu.h     |  5 +++
>  4 files changed, 154 insertions(+)
> 
> diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> index 0d0e5751fc..5ad05f996a 100644
> --- a/hw/i386/rdt.c
> +++ b/hw/i386/rdt.c
> @@ -17,8 +17,18 @@
>  #define MAX_L2_MASK_COUNT      48
>  #define MAX_MBA_THRTL_COUNT    31
>  
> +/* RDT L3 Allocation features */
> +#define CPUID_10_1_EAX_CBM_LENGTH       0xf
> +#define CPUID_10_1_EBX_CBM              0x0
> +#define CPUID_10_1_ECX_CDP              0x0 // to enable, it would be (1U << 2)
>  #define CPUID_10_1_EDX_COS_MAX          MAX_L3_MASK_COUNT
> +/* RDT L2 Allocation features*/
> +#define CPUID_10_2_EAX_CBM_LENGTH       0xf
> +#define CPUID_10_2_EBX_CBM              0x0
>  #define CPUID_10_2_EDX_COS_MAX          MAX_L2_MASK_COUNT
> +/* RDT MBA features */
> +#define CPUID_10_3_EAX_THRTL_MAX        89
> +#define CPUID_10_3_ECX_LINEAR_RESPONSE (1U << 2)
>  #define CPUID_10_3_EDX_COS_MAX          MAX_MBA_THRTL_COUNT
>  
>  #define TYPE_RDT "rdt"
> @@ -61,8 +71,27 @@ struct RDTState {
>  
>  struct RDTStateClass { };
>  
> +uint32_t rdt_get_cpuid_15_0_edx_l3(void) { return CPUID_15_1_EDX_L3_OCCUPANCY | CPUID_15_1_EDX_L3_TOTAL_BW | CPUID_15_1_EDX_L3_LOCAL_BW; }
> +
> +uint32_t rdt_cpuid_15_1_edx_l3_total_bw_enabled(void) { return CPUID_15_1_EDX_L3_TOTAL_BW; }
> +uint32_t rdt_cpuid_15_1_edx_l3_local_bw_enabled(void) { return CPUID_15_1_EDX_L3_LOCAL_BW; }
> +uint32_t rdt_cpuid_15_1_edx_l3_occupancy_enabled(void) { return CPUID_15_1_EDX_L3_OCCUPANCY; }
> +
> +uint32_t rdt_cpuid_10_0_ebx_l3_cat_enabled(void) { return CPUID_10_0_EBX_L3_CAT; }
> +uint32_t rdt_cpuid_10_0_ebx_l2_cat_enabled(void) { return CPUID_10_0_EBX_L2_CAT; }
> +uint32_t rdt_cpuid_10_0_ebx_l2_mba_enabled(void) { return CPUID_10_0_EBX_MBA; }
> +
> +uint32_t rdt_get_cpuid_10_1_eax_cbm_length(void) { return CPUID_10_1_EAX_CBM_LENGTH; }
> +uint32_t rdt_cpuid_10_1_ebx_cbm_enabled(void) { return CPUID_10_1_EBX_CBM; }
> +uint32_t rdt_cpuid_10_1_ecx_cdp_enabled(void) { return CPUID_10_1_ECX_CDP; }
>  uint32_t rdt_get_cpuid_10_1_edx_cos_max(void) { return CPUID_10_1_EDX_COS_MAX; }
> +
> +uint32_t rdt_get_cpuid_10_2_eax_cbm_length(void) { return CPUID_10_2_EAX_CBM_LENGTH; }
> +uint32_t rdt_cpuid_10_2_ebx_cbm_enabled(void) { return CPUID_10_2_EBX_CBM; }
>  uint32_t rdt_get_cpuid_10_2_edx_cos_max(void) { return CPUID_10_2_EDX_COS_MAX; }
> +
> +uint32_t rdt_get_cpuid_10_3_eax_thrtl_max(void) { return CPUID_10_3_EAX_THRTL_MAX; }
> +uint32_t rdt_cpuid_10_3_eax_linear_response_enabled(void) { return CPUID_10_3_ECX_LINEAR_RESPONSE; }
>  uint32_t rdt_get_cpuid_10_3_edx_cos_max(void) { return CPUID_10_3_EDX_COS_MAX; }
>  
>  bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc) {
> diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
> index 51d36822f0..74aba33995 100644
> --- a/include/hw/i386/rdt.h
> +++ b/include/hw/i386/rdt.h
> @@ -4,15 +4,44 @@
>  #include <stdbool.h>
>  #include <stdint.h>
>  
> +/* RDT L3 Cache Monitoring Technology */
> +#define CPUID_15_0_EDX_L3               (1U << 1)
> +#define CPUID_15_1_EDX_L3_OCCUPANCY     (1U << 0)
> +#define CPUID_15_1_EDX_L3_TOTAL_BW      (1U << 1)
> +#define CPUID_15_1_EDX_L3_LOCAL_BW      (1U << 2)
> +
> +/* RDT Cache Allocation Technology */
> +#define CPUID_10_0_EBX_L3_CAT           (1U << 1)
> +#define CPUID_10_0_EBX_L2_CAT           (1U << 2)
> +#define CPUID_10_0_EBX_MBA              (1U << 3)
> +#define CPUID_10_0_EDX CPUID_10_0_EBX_L3_CAT | CPUID_10_0_EBX_L2_CAT | CPUID_10_0_EBX_MBA
> +
>  typedef struct RDTState RDTState;
>  typedef struct RDTStateInstance RDTStateInstance;
>  typedef struct RDTMonitor RDTMonitor;
>  typedef struct RDTAllocation RDTAllocation;
>  
> +uint32_t rdt_get_cpuid_15_0_edx_l3(void);
> +
> +uint32_t rdt_cpuid_15_1_edx_l3_total_bw_enabled(void);
> +uint32_t rdt_cpuid_15_1_edx_l3_local_bw_enabled(void);
> +uint32_t rdt_cpuid_15_1_edx_l3_occupancy_enabled(void);
> +
> +uint32_t rdt_cpuid_10_0_ebx_l3_cat_enabled(void);
> +uint32_t rdt_cpuid_10_0_ebx_l2_cat_enabled(void);
> +uint32_t rdt_cpuid_10_0_ebx_l2_mba_enabled(void);
> +
> +uint32_t rdt_get_cpuid_10_1_eax_cbm_length(void);
> +uint32_t rdt_cpuid_10_1_ebx_cbm_enabled(void);
> +uint32_t rdt_cpuid_10_1_ecx_cdp_enabled(void);
>  uint32_t rdt_get_cpuid_10_1_edx_cos_max(void);
>  
> +uint32_t rdt_get_cpuid_10_2_eax_cbm_length(void);
> +uint32_t rdt_cpuid_10_2_ebx_cbm_enabled(void);
>  uint32_t rdt_get_cpuid_10_2_edx_cos_max(void);
>  
> +uint32_t rdt_get_cpuid_10_3_eax_thrtl_max(void);
> +uint32_t rdt_cpuid_10_3_eax_linear_response_enabled(void);
>  uint32_t rdt_get_cpuid_10_3_edx_cos_max(void);
>  
>  bool rdt_associate_rmid_cos(uint64_t msr_ia32_pqr_assoc);
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 4688d140c2..c61981bf82 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -42,6 +42,7 @@
>  #include "hw/boards.h"
>  #include "hw/i386/sgx-epc.h"
>  #endif
> +#include "hw/i386/rdt.h"
>  
>  #include "disas/capstone.h"
>  #include "cpu-internal.h"
> @@ -6629,6 +6630,96 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>          assert(!(*eax & ~0x1f));
>          *ebx &= 0xffff; /* The count doesn't need to be reliable. */
>          break;
> +#ifndef CONFIG_USER_ONLY
> +    case 0xF:
> +        /* Shared Resource Monitoring Enumeration Leaf */
> +        *eax = 0;
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_PQM))
> +            break;
> +        assert(cpu->rdt);
> +        /* Non-zero count is ResId */
> +        switch (count) {
> +            /* Monitoring Resource Type Enumeration */
> +            case 0:
> +                *edx = env->features[FEAT_RDT_15_0_EDX];
> +                *ebx = rdt_max_rmid(cpu->rdt);
> +                break;
> +            /* L3 Cache Monitoring Capability Enumeration Data */
> +            case 1:
> +                /* Upscaling Factor */
> +                *ebx = 1;
> +                /* MaxRMID */
> +                *ecx = rdt_max_rmid(cpu->rdt);
> +                /* Set L3 Total BW */
comments fairly obvious from naming of functions so I'd be tempted
to drop them all and have
		   *ecx = rdt_max_rmid(cpu->rdt);
                   *edx = rdt_cpuid_15_1_edx_l3_total_bw_enabled() |
                          rdt_cpuid_15_1_edx_l3_local_bw_enabled() |
                          rdt_cpuid_15_1_edx_l3_occupancy_enabled();

Same for the rest of the cases
> +                *edx |= rdt_cpuid_15_1_edx_l3_total_bw_enabled();
> +                /* Set L3 Local BW */
> +                *edx |= rdt_cpuid_15_1_edx_l3_local_bw_enabled();
> +                /* Set L3 Occupancy */
> +                *edx |= rdt_cpuid_15_1_edx_l3_occupancy_enabled();
> +                break;
> +            default:
> +                break;
> +        }
> +        break;
> +    case 0x10:
> +        /* Shared Resource Director Technology Allocation Enumeration Leaf */
> +        *eax = 0;
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_PQE))
> +            break;
> +        assert(cpu->rdt);
> +        /* Non-zero count is ResId */
> +        switch (count) {
> +            /* Cache Allocation Technology Available Resource Types */
> +            case 0:
> +                /* Set L3 CAT */
> +                *ebx |= rdt_cpuid_10_0_ebx_l3_cat_enabled();
> +                /* Set L2 CAT */
> +                *ebx |= rdt_cpuid_10_0_ebx_l2_cat_enabled();
> +                /* Set MBA */
> +                *ebx |= rdt_cpuid_10_0_ebx_l2_mba_enabled();
> +                // *edx = env->features[FEAT_RDT_10_0_EBX];

Make sure to clean up any commented out code for v2.

> +                break;
> +            case 1:
> +                /* Length of capacity bitmask in -1 notation */
> +                *eax = rdt_get_cpuid_10_1_eax_cbm_length();
> +                /* Capability bit mask */
> +                *ebx = rdt_cpuid_10_1_ebx_cbm_enabled();
> +                /* Code and Data priotitization */
> +                *ecx |= rdt_cpuid_10_1_ecx_cdp_enabled();
> +                /* Support for n COS masks (zero-referenced)*/
> +                *edx =  rdt_get_cpuid_10_1_edx_cos_max();
> +                break;
> +            case 2:
> +                /* Length of capacity bitmask in -1 notation */
> +                *eax = rdt_get_cpuid_10_2_eax_cbm_length();
> +                /* Capability bit mask */
> +                *ebx = rdt_cpuid_10_2_ebx_cbm_enabled();
> +                /* Support for n COS masks (zero-referenced)*/
> +                *edx =  rdt_get_cpuid_10_2_edx_cos_max();
> +                break;
> +            case 3:
> +                /* Max throttling value -1 (89 means 90) */
> +                *eax = rdt_get_cpuid_10_3_eax_thrtl_max();
> +                /* Linear response of delay values */
> +                *ecx = rdt_cpuid_10_3_eax_linear_response_enabled();
> +                /* Max number of CLOS -1 (15 means 16) */
> +                *edx = rdt_get_cpuid_10_3_edx_cos_max();
> +                break;
> +            default:
> +                *eax = 0;
> +                *ebx = 0;
> +                *ecx = 0;
> +                *edx = 0;
already done above.
> +                break;
> +        }
> +        break;
> +#endif
>      case 0x1C:
>          if (cpu->enable_pmu && (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
>              x86_cpu_get_supported_cpuid(0x1C, 0, eax, ebx, ecx, edx);




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v1 1/9] Add Intel RDT device to config.
  2024-07-26 10:24   ` Jonathan Cameron via
@ 2024-09-04 14:14     ` Hendrik Wüthrich
  0 siblings, 0 replies; 18+ messages in thread
From: Hendrik Wüthrich @ 2024-09-04 14:14 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: qemu-devel, eduardo, richard.henderson, marcel.apfelbaum, mst,
	pbonzini, peternewman

On Fri, Jul 26, 2024 at 12:24 PM Jonathan Cameron
<Jonathan.Cameron@huawei.com> wrote:
>
> On Fri, 19 Jul 2024 16:29:21 +0000
> Hendrik Wuethrich <whendrik@google.com> wrote:
>
> > From: ‪Hendrik Wüthrich <whendrik@google.com>
> >
> > Change config to show RDT, add minimal code to the rdt.c module to make
> > sure things still compile.
> >
> > Signed-off-by: Hendrik Wüthrich <whendrik@google.com>
>
> Hi Hendrik
>
> Great to see emulation of this. Will be handy for testing
> kernel changes etc.

Hi Jonathan, thank you very much for the review, and very sorry
for the late reply.

> Not convinced it's worth a separate patch just to add stubs.
> Why not at least bring some real code in with this?
>
> > ---
> >  hw/i386/Kconfig       |  4 ++++
> >  hw/i386/meson.build   |  1 +
> >  hw/i386/rdt.c         | 49 +++++++++++++++++++++++++++++++++++++++++++
> >  include/hw/i386/rdt.h | 12 +++++++++++
> >  4 files changed, 66 insertions(+)
> >  create mode 100644 hw/i386/rdt.c
> >  create mode 100644 include/hw/i386/rdt.h
> >
> > diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
> > index f4a33b6c08..4dd05ed6f2 100644
> > --- a/hw/i386/Kconfig
> > +++ b/hw/i386/Kconfig
> > @@ -10,6 +10,9 @@ config SGX
> >      bool
> >      depends on KVM
> >
> > +config RDT
> > +    bool
> > +
> >  config PC
> >      bool
> >      imply APPLESMC
> > @@ -26,6 +29,7 @@ config PC
> >      imply QXL
> >      imply SEV
> >      imply SGX
> > +    imply RDT
> >      imply TEST_DEVICES
> >      imply TPM_CRB
> >      imply TPM_TIS_ISA
> > diff --git a/hw/i386/meson.build b/hw/i386/meson.build
> > index 03aad10df7..fdbf5962b5 100644
> > --- a/hw/i386/meson.build
> > +++ b/hw/i386/meson.build
> > @@ -21,6 +21,7 @@ i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
> >  i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c'))
> >  i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c','sgx.c'),
> >                                  if_false: files('sgx-stub.c'))
> > +i386_ss.add(when: 'CONFIG_RDT', if_true: files('rdt.c'))
> >
> >  i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
> >  i386_ss.add(when: 'CONFIG_PC', if_true: files(
> > diff --git a/hw/i386/rdt.c b/hw/i386/rdt.c
> > new file mode 100644
> > index 0000000000..0a5e95606b
> > --- /dev/null
> > +++ b/hw/i386/rdt.c
>
> License etc missing.
>
> > @@ -0,0 +1,49 @@
> > +#include "qemu/osdep.h"
> > +#include "hw/i386/rdt.h"
> > +#include <stdint.h>
> > +#include "hw/qdev-properties.h"
> > +#include "qemu/typedefs.h"
> > +#include "qom/object.h"
> > +#include "target/i386/cpu.h"
> > +#include "hw/isa/isa.h"
>
> Ordering seems a bit random.  I don't really mind what order
> they are in but it is easier to pick an option so it
> becomes obvious where to put things later.
>
> Also better to bring these in when they are needed so it
> is obvious why they are here.
>
>
> > +
> > +#define TYPE_RDT "rdt"
> > +
> > +OBJECT_DECLARE_TYPE(RDTState, RDTStateClass, RDT);
> > +
> > +struct RDTState {
> > +    ISADevice parent;
> > +};
> > +
> > +struct RDTStateClass { };
> I'd do
> ...Class {
> };
>
> As will reduce noise in later patches assuming this will have
> content.
>
>
> > +
> > +OBJECT_DEFINE_TYPE(RDTState, rdt, RDT, ISA_DEVICE);
> > +
> > +static Property rdt_properties[] = {
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void rdt_init(Object *obj)
>
> Not used?
>
> > +{
> > +}
> > +
> > +static void rdt_realize(DeviceState *dev, Error **errp)
> > +{
> > +}
> > +
> > +static void rdt_finalize(Object *obj)
> > +{
> > +}
>
> Not used?

Realize will be removed in V2 until needed. init and
finalize are necessary to build the device, as far as I
can tell.
>
> > +
> > +static void rdt_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->hotpluggable = false;
> > +    dc->desc = "RDT";
> > +    dc->user_creatable = true;
> > +    dc->realize = rdt_realize;
> > +
> > +    device_class_set_props(dc, rdt_properties);
> > +}
> > +
> > diff --git a/include/hw/i386/rdt.h b/include/hw/i386/rdt.h
> > new file mode 100644
> > index 0000000000..45e34d3103
> > --- /dev/null
> > +++ b/include/hw/i386/rdt.h
> > @@ -0,0 +1,12 @@
> > +#ifndef HW_RDT_H
> > +#define HW_RDT_H
> > +
> > +#include <stdbool.h>
> > +#include <stdint.h>
>
> Not used so don't include them until needed.
>
> > +
> > +typedef struct RDTState RDTState;
> > +typedef struct RDTStateInstance RDTStateInstance;
> > +typedef struct RDTMonitor RDTMonitor;
> > +typedef struct RDTAllocation RDTAllocation;
> > +
> > +#endif
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2024-09-04 14:15 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-19 16:29 [PATCH v1 0/9] target:386/ Emulate Intel RDT features needed to mount ResCtrl in Linux Hendrik Wuethrich
2024-07-19 16:29 ` [PATCH v1 1/9] Add Intel RDT device to config Hendrik Wuethrich
2024-07-26 10:24   ` Jonathan Cameron via
2024-09-04 14:14     ` Hendrik Wüthrich
2024-07-19 16:29 ` [PATCH v1 2/9] Add state for RDT device Hendrik Wuethrich
2024-07-26 10:33   ` Jonathan Cameron via
2024-07-19 16:29 ` [PATCH v1 3/9] Add init and realize funciontality " Hendrik Wuethrich
2024-07-26 10:41   ` Jonathan Cameron via
2024-07-26 10:42   ` Jonathan Cameron via
2024-07-19 16:29 ` [PATCH v1 4/9] Add RDT functionality Hendrik Wuethrich
2024-07-26 10:51   ` Jonathan Cameron via
2024-07-19 16:29 ` [PATCH v1 5/9] Add RDT device interface through MSRs Hendrik Wuethrich
2024-07-26 10:57   ` Jonathan Cameron via
2024-07-19 16:29 ` [PATCH v1 6/9] Add CPUID enumeration for RDT Hendrik Wuethrich
2024-07-26 12:09   ` Jonathan Cameron via
2024-07-19 16:29 ` [PATCH v1 7/9] Add RDT feature flags Hendrik Wuethrich
2024-07-19 16:29 ` [PATCH v1 8/9] Adjust CPUID level for RDT features Hendrik Wuethrich
2024-07-19 16:29 ` [PATCH v1 9/9] Adjust level for RDT on full_cpuid_auto_level Hendrik Wuethrich

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).