[PATCH v3] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways
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
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
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
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
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
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