[PATCH v3] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways

2024-05-07 Thread Yao Xingtao via
Since the kernel does not check the interleave capability, a
3-way, 6-way, 12-way or 16-way region can be create normally.

Applications can access the memory of 16-way region normally because
qemu can convert hpa to dpa correctly for the power of 2 interleave
ways, after kernel implementing the check, this kind of region will
not be created any more.

For non power of 2 interleave ways, applications could not access the
memory normally and may occur some unexpected behaviors, such as
segmentation fault.

So implements this feature is needed.

Link: 
https://lore.kernel.org/linux-cxl/3e84b919-7631-d1db-3e1d-33000f3f3...@fujitsu.com/
Signed-off-by: Yao Xingtao 
---
 hw/cxl/cxl-component-utils.c |  9 +++--
 hw/mem/cxl_type3.c   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index cd116c0401..473895948b 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -243,8 +243,13 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t 
*write_msk,
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_4K, 1);
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
  POISON_ON_ERR_CAP, 0);
-ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
-ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
+if (type == CXL2_TYPE3_DEVICE) {
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 1);
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 1);
+} else {
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
+}
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO, 0);
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
  UIO_DECODER_COUNT, 0);
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 3e42490b6c..b755318838 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -804,10 +804,17 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr 
host_addr, uint64_t *dpa)
 continue;
 }
 
-*dpa = dpa_base +
-((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
- ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
-  >> iw));
+if (iw < 8) {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
+  >> iw));
+} else {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) & hpa_offset)
+   >> (ig + iw)) / 3) << (ig + 8)));
+}
 
 return true;
 }
-- 
2.37.3




[PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways

2024-04-06 Thread Yao Xingtao via
Since the kernel does not check the interleave capability, a
3-way, 6-way, 12-way or 16-way region can be create normally.

Applications can access the memory of 16-way region normally because
qemu can convert hpa to dpa correctly for the power of 2 interleave
ways, after kernel implementing the check, this kind of region will
not be created any more.

For non power of 2 interleave ways, applications could not access the
memory normally and may occur some unexpected behaviors, such as
segmentation fault.

So implements this feature is needed.

Link: 
https://lore.kernel.org/linux-cxl/3e84b919-7631-d1db-3e1d-33000f3f3...@fujitsu.com/
Signed-off-by: Yao Xingtao 
---
 hw/mem/cxl_type3.c | 18 ++
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index b0a7e9f11b..d6ef784e96 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -805,10 +805,17 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr 
host_addr, uint64_t *dpa)
 continue;
 }
 
-*dpa = dpa_base +
-((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
- ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
-  >> iw));
+if (iw < 8) {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
+  >> iw));
+} else {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) & hpa_offset)
+   >> (ig + iw)) / 3) << (ig + 8)));
+}
 
 return true;
 }
@@ -906,6 +913,9 @@ static void ct3d_reset(DeviceState *dev)
 uint32_t *write_msk = ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;
 
 cxl_component_register_init_common(reg_state, write_msk, 
CXL2_TYPE3_DEVICE);
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 1);
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 1);
+
 cxl_device_register_init_t3(ct3d);
 
 /*
-- 
2.37.3




[PATCH] mem/cxl_type3: fix hpa to dpa logic

2024-03-26 Thread Yao Xingtao via
In 3, 6, 12 interleave ways, we could not access cxl memory properly,
and when the process is running on it, a 'segmentation fault' error will
occur.

According to the CXL specification '8.2.4.20.13 Decoder Protection',
there are two branches to convert HPA to DPA:
b1: Decoder[m].IW < 8 (for 1, 2, 4, 8, 16 interleave ways)
b2: Decoder[m].IW >= 8 (for 3, 6, 12 interleave ways)

but only b1 has been implemented.

To solve this issue, we should implement b2:
  DPAOffset[51:IG+8]=HPAOffset[51:IG+IW] / 3
  DPAOffset[IG+7:0]=HPAOffset[IG+7:0]
  DPA=DPAOffset + Decoder[n].DPABase

Links: 
https://lore.kernel.org/linux-cxl/3e84b919-7631-d1db-3e1d-33000f3f3...@fujitsu.com/
Signed-off-by: Yao Xingtao 
---
 hw/mem/cxl_type3.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index b0a7e9f11b..2c1218fb12 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -805,10 +805,17 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr 
host_addr, uint64_t *dpa)
 continue;
 }
 
-*dpa = dpa_base +
-((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
- ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
-  >> iw));
+if (iw < 8) {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
+  >> iw));
+} else {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) & hpa_offset)
+   >> (ig + iw)) / 3) << (ig + 8)));
+}
 
 return true;
 }
-- 
2.37.3




[PATCH v3] contrib/plugins/execlog: Fix compiler warning

2024-03-25 Thread Yao Xingtao via
1. The g_pattern_match_string() is deprecated when glib2 version >= 2.70.
   Use g_pattern_spec_match_string() instead to avoid this problem.

2. The type of second parameter in g_ptr_array_add() is
   'gpointer' {aka 'void *'}, but the type of reg->name is 'const char*'.
   Cast the type of reg->name to 'gpointer' to avoid this problem.

compiler warning message:
/root/qemu/contrib/plugins/execlog.c:330:17: warning: ‘g_pattern_match_string’
is deprecated: Use 'g_pattern_spec_match_string'
instead [-Wdeprecated-declarations]
  330 | if (g_pattern_match_string(pat, rd->name) ||
  | ^~
In file included from /usr/include/glib-2.0/glib.h:67,
 from /root/qemu/contrib/plugins/execlog.c:9:
/usr/include/glib-2.0/glib/gpattern.h:57:15: note: declared here
   57 | gboolean  g_pattern_match_string   (GPatternSpec *pspec,
  |   ^~
/root/qemu/contrib/plugins/execlog.c:331:21: warning: ‘g_pattern_match_string’
is deprecated: Use 'g_pattern_spec_match_string'
instead [-Wdeprecated-declarations]
  331 | g_pattern_match_string(pat, rd_lower)) {
  | ^~
/usr/include/glib-2.0/glib/gpattern.h:57:15: note: declared here
   57 | gboolean  g_pattern_match_string   (GPatternSpec *pspec,
  |   ^~
/root/qemu/contrib/plugins/execlog.c:339:63: warning: passing argument 2 of
‘g_ptr_array_add’ discards ‘const’ qualifier from pointer target type
[-Wdiscarded-qualifiers]
  339 | g_ptr_array_add(all_reg_names, reg->name);
  |~~~^~
In file included from /usr/include/glib-2.0/glib.h:33:
/usr/include/glib-2.0/glib/garray.h:198:62: note: expected
‘gpointer’ {aka ‘void *’} but argument is of type ‘const char *’
  198 |gpointer  data);
  |~~^~~~

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2210
Signed-off-by: Yao Xingtao 
---
 contrib/plugins/execlog.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
index a1dfd59ab7..fab18113d4 100644
--- a/contrib/plugins/execlog.c
+++ b/contrib/plugins/execlog.c
@@ -311,6 +311,24 @@ static Register 
*init_vcpu_register(qemu_plugin_reg_descriptor *desc)
 return reg;
 }
 
+/*
+ * g_pattern_match_string has been deprecated in Glib since 2.70 and
+ * will complain about it if you try to use it. Fortunately the
+ * signature of both functions is the same making it easy to work
+ * around.
+ */
+static inline
+gboolean g_pattern_spec_match_string_qemu(GPatternSpec *pspec,
+  const gchar *string)
+{
+#if GLIB_CHECK_VERSION(2, 70, 0)
+return g_pattern_spec_match_string(pspec, string);
+#else
+return g_pattern_match_string(pspec, string);
+#endif
+};
+#define g_pattern_spec_match_string(p, s) g_pattern_spec_match_string_qemu(p, 
s)
+
 static GPtrArray *registers_init(int vcpu_index)
 {
 g_autoptr(GPtrArray) registers = g_ptr_array_new();
@@ -327,8 +345,8 @@ static GPtrArray *registers_init(int vcpu_index)
 for (int p = 0; p < rmatches->len; p++) {
 g_autoptr(GPatternSpec) pat = 
g_pattern_spec_new(rmatches->pdata[p]);
 g_autofree gchar *rd_lower = g_utf8_strdown(rd->name, -1);
-if (g_pattern_match_string(pat, rd->name) ||
-g_pattern_match_string(pat, rd_lower)) {
+if (g_pattern_spec_match_string(pat, rd->name) ||
+g_pattern_spec_match_string(pat, rd_lower)) {
 Register *reg = init_vcpu_register(rd);
 g_ptr_array_add(registers, reg);
 
@@ -336,7 +354,7 @@ static GPtrArray *registers_init(int vcpu_index)
 if (disas_assist) {
 g_mutex_lock(_reg_name_lock);
 if (!g_ptr_array_find(all_reg_names, reg->name, NULL)) 
{
-g_ptr_array_add(all_reg_names, reg->name);
+g_ptr_array_add(all_reg_names, 
(gpointer)reg->name);
 }
 g_mutex_unlock(_reg_name_lock);
 }
-- 
2.37.3




[PATCH v2] contrib/plugins/execlog: Fix compiler warning

2024-03-25 Thread Yao Xingtao via
1. The g_pattern_match_string() is deprecated when glib2 version >= 2.70.
   Use g_pattern_spec_match_string() instead to avoid this problem.

2. The type of second parameter in g_ptr_array_add() is
   'gpointer' {aka 'void *'}, but the type of reg->name is 'const char*'.
   Cast the type of reg->name to 'gpointer' to avoid this problem.

compiler warning message:
/root/qemu/contrib/plugins/execlog.c:330:17: warning: ‘g_pattern_match_string’
is deprecated: Use 'g_pattern_spec_match_string'
instead [-Wdeprecated-declarations]
  330 | if (g_pattern_match_string(pat, rd->name) ||
  | ^~
In file included from /usr/include/glib-2.0/glib.h:67,
 from /root/qemu/contrib/plugins/execlog.c:9:
/usr/include/glib-2.0/glib/gpattern.h:57:15: note: declared here
   57 | gboolean  g_pattern_match_string   (GPatternSpec *pspec,
  |   ^~
/root/qemu/contrib/plugins/execlog.c:331:21: warning: ‘g_pattern_match_string’
is deprecated: Use 'g_pattern_spec_match_string'
instead [-Wdeprecated-declarations]
  331 | g_pattern_match_string(pat, rd_lower)) {
  | ^~
/usr/include/glib-2.0/glib/gpattern.h:57:15: note: declared here
   57 | gboolean  g_pattern_match_string   (GPatternSpec *pspec,
  |   ^~
/root/qemu/contrib/plugins/execlog.c:339:63: warning: passing argument 2 of
‘g_ptr_array_add’ discards ‘const’ qualifier from pointer target type
[-Wdiscarded-qualifiers]
  339 | g_ptr_array_add(all_reg_names, reg->name);
  |~~~^~
In file included from /usr/include/glib-2.0/glib.h:33:
/usr/include/glib-2.0/glib/garray.h:198:62: note: expected
‘gpointer’ {aka ‘void *’} but argument is of type ‘const char *’
  198 |gpointer  data);
  |~~^~~~

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2210
Signed-off-by: Yao Xingtao 
---
 contrib/plugins/execlog.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
index a1dfd59ab7..09654910ee 100644
--- a/contrib/plugins/execlog.c
+++ b/contrib/plugins/execlog.c
@@ -327,8 +327,13 @@ static GPtrArray *registers_init(int vcpu_index)
 for (int p = 0; p < rmatches->len; p++) {
 g_autoptr(GPatternSpec) pat = 
g_pattern_spec_new(rmatches->pdata[p]);
 g_autofree gchar *rd_lower = g_utf8_strdown(rd->name, -1);
+#if GLIB_CHECK_VERSION(2, 70, 0)
+if (g_pattern_spec_match_string(pat, rd->name) ||
+g_pattern_spec_match_string(pat, rd_lower)) {
+#else
 if (g_pattern_match_string(pat, rd->name) ||
 g_pattern_match_string(pat, rd_lower)) {
+#endif
 Register *reg = init_vcpu_register(rd);
 g_ptr_array_add(registers, reg);
 
@@ -336,7 +341,7 @@ static GPtrArray *registers_init(int vcpu_index)
 if (disas_assist) {
 g_mutex_lock(_reg_name_lock);
 if (!g_ptr_array_find(all_reg_names, reg->name, NULL)) 
{
-g_ptr_array_add(all_reg_names, reg->name);
+g_ptr_array_add(all_reg_names, 
(gpointer)reg->name);
 }
 g_mutex_unlock(_reg_name_lock);
 }
-- 
2.37.3




[PATCH] contrib/plugins/execlog: Fix compiler warning

2024-03-19 Thread Yao Xingtao via
1. The g_pattern_match_string() is deprecated when glib2 version >= 2.70.
   Use g_pattern_spec_match_string() instead to avoid this problem.

2. The type of second parameter in g_ptr_array_add() is
   'gpointer' {aka 'void *'}, but the type of reg->name is 'const char*'.
   Cast the type of reg->name to 'gpointer' to avoid this problem.

compiler warning message:
/root/qemu/contrib/plugins/execlog.c:330:17: warning: ‘g_pattern_match_string’
is deprecated: Use 'g_pattern_spec_match_string'
instead [-Wdeprecated-declarations]
  330 | if (g_pattern_match_string(pat, rd->name) ||
  | ^~
In file included from /usr/include/glib-2.0/glib.h:67,
 from /root/qemu/contrib/plugins/execlog.c:9:
/usr/include/glib-2.0/glib/gpattern.h:57:15: note: declared here
   57 | gboolean  g_pattern_match_string   (GPatternSpec *pspec,
  |   ^~
/root/qemu/contrib/plugins/execlog.c:331:21: warning: ‘g_pattern_match_string’
is deprecated: Use 'g_pattern_spec_match_string'
instead [-Wdeprecated-declarations]
  331 | g_pattern_match_string(pat, rd_lower)) {
  | ^~
/usr/include/glib-2.0/glib/gpattern.h:57:15: note: declared here
   57 | gboolean  g_pattern_match_string   (GPatternSpec *pspec,
  |   ^~
/root/qemu/contrib/plugins/execlog.c:339:63: warning: passing argument 2 of
‘g_ptr_array_add’ discards ‘const’ qualifier from pointer target type
[-Wdiscarded-qualifiers]
  339 | g_ptr_array_add(all_reg_names, reg->name);
  |~~~^~
In file included from /usr/include/glib-2.0/glib.h:33:
/usr/include/glib-2.0/glib/garray.h:198:62: note: expected
‘gpointer’ {aka ‘void *’} but argument is of type ‘const char *’
  198 |gpointer  data);
  |~~^~~~

Signed-off-by: Yao Xingtao 
---
 contrib/plugins/execlog.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
index a1dfd59ab7..41f6774116 100644
--- a/contrib/plugins/execlog.c
+++ b/contrib/plugins/execlog.c
@@ -327,8 +327,13 @@ static GPtrArray *registers_init(int vcpu_index)
 for (int p = 0; p < rmatches->len; p++) {
 g_autoptr(GPatternSpec) pat = 
g_pattern_spec_new(rmatches->pdata[p]);
 g_autofree gchar *rd_lower = g_utf8_strdown(rd->name, -1);
+#if GLIB_VERSION_MAX_ALLOWED < G_ENCODE_VERSION(2, 70)
 if (g_pattern_match_string(pat, rd->name) ||
 g_pattern_match_string(pat, rd_lower)) {
+#else
+if (g_pattern_spec_match_string(pat, rd->name) ||
+g_pattern_spec_match_string(pat, rd_lower)) {
+#endif
 Register *reg = init_vcpu_register(rd);
 g_ptr_array_add(registers, reg);
 
@@ -336,7 +341,7 @@ static GPtrArray *registers_init(int vcpu_index)
 if (disas_assist) {
 g_mutex_lock(_reg_name_lock);
 if (!g_ptr_array_find(all_reg_names, reg->name, NULL)) 
{
-g_ptr_array_add(all_reg_names, reg->name);
+g_ptr_array_add(all_reg_names, 
(gpointer)reg->name);
 }
 g_mutex_unlock(_reg_name_lock);
 }
-- 
2.37.3