diff mbox series

[1/1] Skip flatview_simplify() for specific cpu vendor

Message ID 20200903094935.2361-2-FelixCui-oc@zhaoxin.com
State Superseded
Headers show
Series Skip flatview_simplify() for specific cpu vendor | expand

Commit Message

FelixCuioc Sept. 3, 2020, 9:49 a.m. UTC
Flatview_simplify() will merge many address ranges
into one range.When a part of the big range needs
to be changed,this will cause some innocent mappings
to be unmapped.So we want to skip flatview_simplify().

Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
---
 softmmu/memory.c  | 16 +++++++++++++++-
 target/i386/cpu.c |  8 ++++++++
 target/i386/cpu.h |  3 +++
 3 files changed, 26 insertions(+), 1 deletion(-)

Comments

Paolo Bonzini Sept. 3, 2020, 10:37 a.m. UTC | #1
On 03/09/20 11:49, FelixCuioc wrote:
> Flatview_simplify() will merge many address ranges
> into one range.When a part of the big range needs
> to be changed,this will cause some innocent mappings
> to be unmapped.So we want to skip flatview_simplify().
> 
> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>

This has several issues.  In no particular order:

1) you're adding host_get_vendor to target/i386/cpu.c so this does not
even build for the default "../configure && make".

2) you're adding a check for the host, but the bug applies to all hosts.
 If there is a bug on x86 hardware emulation, it should be fixed even
when emulating x86 from ARM.

3) you're not explaining what is the big range and how the bug is
manifesting.

I think you're seeing issues when a guest accesses an adjacent mapping
between the delete and add phases of the KVM MemoryListener.  We're
considering fixing that in the kernel, by adding a new ioctl that
changes the whole memory map in a single step.  I am CCing Peter Xu.

Paolo


> ---
>  softmmu/memory.c  | 16 +++++++++++++++-
>  target/i386/cpu.c |  8 ++++++++
>  target/i386/cpu.h |  3 +++
>  3 files changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/softmmu/memory.c b/softmmu/memory.c
> index 70b93104e8..348e9db622 100644
> --- a/softmmu/memory.c
> +++ b/softmmu/memory.c
> @@ -699,6 +699,18 @@ static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
>      return NULL;
>  }
>  
> +static bool skip_simplify(void)
> +{
> +    char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
> +    host_get_vendor(vendor);
> +    if (!strncmp(vendor, CPUID_VENDOR_VIA, strlen(CPUID_VENDOR_VIA))
> +        || !strncmp(vendor, CPUID_VENDOR_ZHAOXIN,
> +                    strlen(CPUID_VENDOR_ZHAOXIN))) {
> +        return true;
> +    }
> +    return false;
> +}
> +
>  /* Render a memory topology into a list of disjoint absolute ranges. */
>  static FlatView *generate_memory_topology(MemoryRegion *mr)
>  {
> @@ -712,7 +724,9 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)
>                               addrrange_make(int128_zero(), int128_2_64()),
>                               false, false);
>      }
> -    flatview_simplify(view);
> +    if (!skip_simplify()) {
> +        flatview_simplify(view);
> +    }
>  
>      view->dispatch = address_space_dispatch_new(view);
>      for (i = 0; i < view->nr; i++) {
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 49d8958528..08508c8580 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1664,6 +1664,14 @@ void host_cpuid(uint32_t function, uint32_t count,
>          *edx = vec[3];
>  }
>  
> +void host_get_vendor(char *vendor)
> +{
> +    uint32_t eax, ebx, ecx, edx;
> +
> +    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
> +    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
> +}
> +
>  void host_vendor_fms(char *vendor, int *family, int *model, int *stepping)
>  {
>      uint32_t eax, ebx, ecx, edx;
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index d3097be6a5..14c8b4c09f 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -832,6 +832,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
>  
>  #define CPUID_VENDOR_VIA   "CentaurHauls"
>  
> +#define CPUID_VENDOR_ZHAOXIN   "  Shanghai  "
> +
>  #define CPUID_VENDOR_HYGON    "HygonGenuine"
>  
>  #define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \
> @@ -1917,6 +1919,7 @@ void cpu_clear_apic_feature(CPUX86State *env);
>  void host_cpuid(uint32_t function, uint32_t count,
>                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
>  void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);
> +void host_get_vendor(char *vendor);
>  
>  /* helper.c */
>  bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>
FelixCuioc Sept. 3, 2020, 11:24 a.m. UTC | #2
>I think you're seeing issues when a guest accesses an adjacent mapping

>between the delete and add phases of the KVM MemoryListener.


>We're considering fixing that in the kernel, by adding a new ioctl that

>changes the whole memory map in a single step.  I am CCing Peter Xu.



hi paolo,

              What you said is very similar to my issues. My problem is happened when a EHCI device accesses an adjacent mapping between the delete and add phases of the VFIO MemoryListener.

VFIO MemoryListener  is also included under address_space_memory.

              Does adding a new ioctl also apply to VFIO MemoryListener?


Best regards

Felixcui-oc


________________________________
发件人: Paolo Bonzini <pbonzini@redhat.com>
发送时间: 2020年9月3日 18:37:47
收件人: FelixCui-oc; Richard Henderson; Eduardo Habkost
抄送: qemu-devel@nongnu.org; RockCui-oc; Tony W Wang-oc; CobeChen-oc; Peter Xu
主题: Re: [PATCH 1/1] Skip flatview_simplify() for specific cpu vendor

On 03/09/20 11:49, FelixCuioc wrote:
> Flatview_simplify() will merge many address ranges

> into one range.When a part of the big range needs

> to be changed,this will cause some innocent mappings

> to be unmapped.So we want to skip flatview_simplify().

>

> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>


This has several issues.  In no particular order:

1) you're adding host_get_vendor to target/i386/cpu.c so this does not
even build for the default "../configure && make".

2) you're adding a check for the host, but the bug applies to all hosts.
 If there is a bug on x86 hardware emulation, it should be fixed even
when emulating x86 from ARM.

3) you're not explaining what is the big range and how the bug is
manifesting.

I think you're seeing issues when a guest accesses an adjacent mapping
between the delete and add phases of the KVM MemoryListener.  We're
considering fixing that in the kernel, by adding a new ioctl that
changes the whole memory map in a single step.  I am CCing Peter Xu.

Paolo


> ---

>  softmmu/memory.c  | 16 +++++++++++++++-

>  target/i386/cpu.c |  8 ++++++++

>  target/i386/cpu.h |  3 +++

>  3 files changed, 26 insertions(+), 1 deletion(-)

>

> diff --git a/softmmu/memory.c b/softmmu/memory.c

> index 70b93104e8..348e9db622 100644

> --- a/softmmu/memory.c

> +++ b/softmmu/memory.c

> @@ -699,6 +699,18 @@ static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)

>      return NULL;

>  }

>

> +static bool skip_simplify(void)

> +{

> +    char vendor[CPUID_VENDOR_SZ + 1] = { 0 };

> +    host_get_vendor(vendor);

> +    if (!strncmp(vendor, CPUID_VENDOR_VIA, strlen(CPUID_VENDOR_VIA))

> +        || !strncmp(vendor, CPUID_VENDOR_ZHAOXIN,

> +                    strlen(CPUID_VENDOR_ZHAOXIN))) {

> +        return true;

> +    }

> +    return false;

> +}

> +

>  /* Render a memory topology into a list of disjoint absolute ranges. */

>  static FlatView *generate_memory_topology(MemoryRegion *mr)

>  {

> @@ -712,7 +724,9 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)

>                               addrrange_make(int128_zero(), int128_2_64()),

>                               false, false);

>      }

> -    flatview_simplify(view);

> +    if (!skip_simplify()) {

> +        flatview_simplify(view);

> +    }

>

>      view->dispatch = address_space_dispatch_new(view);

>      for (i = 0; i < view->nr; i++) {

> diff --git a/target/i386/cpu.c b/target/i386/cpu.c

> index 49d8958528..08508c8580 100644

> --- a/target/i386/cpu.c

> +++ b/target/i386/cpu.c

> @@ -1664,6 +1664,14 @@ void host_cpuid(uint32_t function, uint32_t count,

>          *edx = vec[3];

>  }

>

> +void host_get_vendor(char *vendor)

> +{

> +    uint32_t eax, ebx, ecx, edx;

> +

> +    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);

> +    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);

> +}

> +

>  void host_vendor_fms(char *vendor, int *family, int *model, int *stepping)

>  {

>      uint32_t eax, ebx, ecx, edx;

> diff --git a/target/i386/cpu.h b/target/i386/cpu.h

> index d3097be6a5..14c8b4c09f 100644

> --- a/target/i386/cpu.h

> +++ b/target/i386/cpu.h

> @@ -832,6 +832,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];

>

>  #define CPUID_VENDOR_VIA   "CentaurHauls"

>

> +#define CPUID_VENDOR_ZHAOXIN   "  Shanghai  "

> +

>  #define CPUID_VENDOR_HYGON    "HygonGenuine"

>

>  #define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \

> @@ -1917,6 +1919,7 @@ void cpu_clear_apic_feature(CPUX86State *env);

>  void host_cpuid(uint32_t function, uint32_t count,

>                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);

>  void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);

> +void host_get_vendor(char *vendor);

>

>  /* helper.c */

>  bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,

>
Paolo Bonzini Sept. 3, 2020, 12:08 p.m. UTC | #3
Il gio 3 set 2020, 13:24 FelixCui-oc <FelixCui-oc@zhaoxin.com> ha scritto:

> >I think you're seeing issues when a guest accesses an adjacent mapping
> between the delete and add phases of the KVM MemoryListener.
>
> >We're considering fixing that in the kernel, by adding a new ioctl that
> changes the whole memory map in a single step.  I am CCing Peter Xu.
>
hi paolo,
>
>               What you said is very similar to my issues. My problem is
> happened when a EHCI device accesses an adjacent mapping between the delete
> and add phases of the VFIO MemoryListener.  Does adding a new ioctl also
> apply to VFIO MemoryListener?
>
It would be done separately but it's the same issue. Let's ask Alex
Williamson.

Alex, the issue here is that the delete+add passes are racing against an
assigned device's DMA. For KVM we were thinking of changing the whole
memory map with a single ioctl, but that's much easier because KVM builds
its page tables lazily. It would be possible for the IOMMU too but it would
require a relatively complicated comparison of the old and new memory maps
in the kernel.

Is this something that you think would be acceptable for Linux? Would it
require changes at the IOMMU level or would it be confined to VFIO?

Thanks,

Paolo

> Best regards
>
> Felixcui-oc
>
>
> ------------------------------
> *发件人:* Paolo Bonzini <pbonzini@redhat.com>
> *发送时间:* 2020年9月3日 18:37:47
> *收件人:* FelixCui-oc; Richard Henderson; Eduardo Habkost
> *抄送:* qemu-devel@nongnu.org; RockCui-oc; Tony W Wang-oc; CobeChen-oc;
> Peter Xu
> *主题:* Re: [PATCH 1/1] Skip flatview_simplify() for specific cpu vendor
>
> On 03/09/20 11:49, FelixCuioc wrote:
> > Flatview_simplify() will merge many address ranges
> > into one range.When a part of the big range needs
> > to be changed,this will cause some innocent mappings
> > to be unmapped.So we want to skip flatview_simplify().
> >
> > Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>
> This has several issues.  In no particular order:
>
> 1) you're adding host_get_vendor to target/i386/cpu.c so this does not
> even build for the default "../configure && make".
>
> 2) you're adding a check for the host, but the bug applies to all hosts.
>  If there is a bug on x86 hardware emulation, it should be fixed even
> when emulating x86 from ARM.
>
> 3) you're not explaining what is the big range and how the bug is
> manifesting.
>
> I think you're seeing issues when a guest accesses an adjacent mapping
> between the delete and add phases of the KVM MemoryListener.  We're
> considering fixing that in the kernel, by adding a new ioctl that
> changes the whole memory map in a single step.  I am CCing Peter Xu.
>
> Paolo
>
>
> > ---
> >  softmmu/memory.c  | 16 +++++++++++++++-
> >  target/i386/cpu.c |  8 ++++++++
> >  target/i386/cpu.h |  3 +++
> >  3 files changed, 26 insertions(+), 1 deletion(-)
> >
> > diff --git a/softmmu/memory.c b/softmmu/memory.c
> > index 70b93104e8..348e9db622 100644
> > --- a/softmmu/memory.c
> > +++ b/softmmu/memory.c
> > @@ -699,6 +699,18 @@ static MemoryRegion
> *memory_region_get_flatview_root(MemoryRegion *mr)
> >      return NULL;
> >  }
> >
> > +static bool skip_simplify(void)
> > +{
> > +    char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
> > +    host_get_vendor(vendor);
> > +    if (!strncmp(vendor, CPUID_VENDOR_VIA, strlen(CPUID_VENDOR_VIA))
> > +        || !strncmp(vendor, CPUID_VENDOR_ZHAOXIN,
> > +                    strlen(CPUID_VENDOR_ZHAOXIN))) {
> > +        return true;
> > +    }
> > +    return false;
> > +}
> > +
> >  /* Render a memory topology into a list of disjoint absolute ranges. */
> >  static FlatView *generate_memory_topology(MemoryRegion *mr)
> >  {
> > @@ -712,7 +724,9 @@ static FlatView
> *generate_memory_topology(MemoryRegion *mr)
> >                               addrrange_make(int128_zero(),
> int128_2_64()),
> >                               false, false);
> >      }
> > -    flatview_simplify(view);
> > +    if (!skip_simplify()) {
> > +        flatview_simplify(view);
> > +    }
> >
> >      view->dispatch = address_space_dispatch_new(view);
> >      for (i = 0; i < view->nr; i++) {
> > diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> > index 49d8958528..08508c8580 100644
> > --- a/target/i386/cpu.c
> > +++ b/target/i386/cpu.c
> > @@ -1664,6 +1664,14 @@ void host_cpuid(uint32_t function, uint32_t count,
> >          *edx = vec[3];
> >  }
> >
> > +void host_get_vendor(char *vendor)
> > +{
> > +    uint32_t eax, ebx, ecx, edx;
> > +
> > +    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
> > +    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
> > +}
> > +
> >  void host_vendor_fms(char *vendor, int *family, int *model, int
> *stepping)
> >  {
> >      uint32_t eax, ebx, ecx, edx;
> > diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> > index d3097be6a5..14c8b4c09f 100644
> > --- a/target/i386/cpu.h
> > +++ b/target/i386/cpu.h
> > @@ -832,6 +832,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
> >
> >  #define CPUID_VENDOR_VIA   "CentaurHauls"
> >
> > +#define CPUID_VENDOR_ZHAOXIN   "  Shanghai  "
> > +
> >  #define CPUID_VENDOR_HYGON    "HygonGenuine"
> >
> >  #define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1
> && \
> > @@ -1917,6 +1919,7 @@ void cpu_clear_apic_feature(CPUX86State *env);
> >  void host_cpuid(uint32_t function, uint32_t count,
> >                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t
> *edx);
> >  void host_vendor_fms(char *vendor, int *family, int *model, int
> *stepping);
> > +void host_get_vendor(char *vendor);
> >
> >  /* helper.c */
> >  bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> >
>
>
<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Il gio 3 set 2020, 13:24 FelixCui-oc &lt;<a href="mailto:FelixCui-oc@zhaoxin.com">FelixCui-oc@zhaoxin.com</a>&gt; ha scritto:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div id="m_4531644718691983322divtagdefaultwrapper" style="" dir="ltr"><div dir="ltr" style=""><div id="m_4531644718691983322x_divtagdefaultwrapper" dir="ltr" style=""><p style=""><font face="Calibri, Helvetica, sans-serif, EmojiFont, Apple Color Emoji, Segoe UI Emoji, NotoColorEmoji, Segoe UI Symbol, Android Emoji, EmojiSymbols"><span style="font-size:16px">&gt;I think you&#39;re seeing issues when a guest accesses an adjacent mapping between the delete and add phases of the KVM MemoryListener.  </span></font></p><p style=""><span style="font-family:Calibri,Helvetica,sans-serif,EmojiFont,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,NotoColorEmoji,&quot;Segoe UI Symbol&quot;,&quot;Android Emoji&quot;,EmojiSymbols;font-size:16px">&gt;We&#39;re considering fixing that in the kernel, by adding a new ioctl that changes the whole memory map in a single step.  I am CCing Peter Xu.</span><font face="Calibri, Helvetica, sans-serif, EmojiFont, Apple Color Emoji, Segoe UI Emoji, NotoColorEmoji, Segoe UI Symbol, Android Emoji, EmojiSymbols"><span style="font-size:16px"><br></span></font></p></div></div></div></div></blockquote></div></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div id="m_4531644718691983322divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Helvetica,sans-serif" dir="ltr"><div dir="ltr"><div id="m_4531644718691983322x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,NotoColorEmoji,&quot;Segoe UI Symbol&quot;,&quot;Android Emoji&quot;,EmojiSymbols"><p><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px">hi paolo,</span></p>
<p><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px">              What you said is very similar to my issues. My problem is happened when a EHCI device accesses
 an adjacent mapping between the delete and add phases of the VFIO MemoryListener.</span><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px">  Does adding a new ioctl also apply to VFIO MemoryListener?</span></p></div></div></div></div></blockquote></div></div><div dir="auto"><span style="font-family:sans-serif">It would be done separately but it&#39;s the same issue. Let&#39;s ask Alex Williamson.</span></div><div dir="auto"><span style="font-family:sans-serif"><br></span></div><div dir="auto"><span style="font-family:sans-serif">Alex, the issue here is that the delete+add passes are racing against an assigned device&#39;s DMA. For KVM we were thinking of changing the whole memory map with a single ioctl, but that&#39;s much easier because KVM builds its page tables lazily. It would be possible for the IOMMU too but it would require a relatively complicated comparison of the old and new memory maps in the kernel.</span></div><div dir="auto"><span style="font-family:sans-serif"><br></span></div><div dir="auto"><span style="font-family:sans-serif">Is this something that you think would be acceptable for Linux? Would it require changes at the IOMMU level or would it be confined to VFIO?</span></div><div dir="auto"><span style="font-family:sans-serif"><br></span></div><div dir="auto"><span style="font-family:sans-serif">Thanks,</span></div><div dir="auto"><span style="font-family:sans-serif"><br></span></div><div dir="auto"><span style="font-family:sans-serif">Paolo</span></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div id="m_4531644718691983322divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Helvetica,sans-serif" dir="ltr"><div dir="ltr"><div id="m_4531644718691983322x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,NotoColorEmoji,&quot;Segoe UI Symbol&quot;,&quot;Android Emoji&quot;,EmojiSymbols">
<p><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px"><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px">Best
 regards</span></span></p>
<p><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px"><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px">Felixcui-oc</span></span></p>
<p><span style="color:rgb(33,33,33);font-family:&quot;Microsoft YaHei UI&quot;,&quot;Microsoft YaHei&quot;,微软雅黑,SimSun,宋体,sans-serif,serif,EmojiFont;font-size:13.3333px"><br>
</span></p>
</div>
<hr style="display:inline-block;width:98%">
<div id="m_4531644718691983322x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>发件人:</b> Paolo Bonzini &lt;<a href="mailto:pbonzini@redhat.com" target="_blank" rel="noreferrer">pbonzini@redhat.com</a>&gt;<br>
<b>发送时间:</b> 2020年9月3日 18:37:47<br>
<b>收件人:</b> FelixCui-oc; Richard Henderson; Eduardo Habkost<br>
<b>抄送:</b> <a href="mailto:qemu-devel@nongnu.org" target="_blank" rel="noreferrer">qemu-devel@nongnu.org</a>; RockCui-oc; Tony W Wang-oc; CobeChen-oc; Peter Xu<br>
<b>主题:</b> Re: [PATCH 1/1] Skip flatview_simplify() for specific cpu vendor</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt">
<div>On 03/09/20 11:49, FelixCuioc wrote:<br>
&gt; Flatview_simplify() will merge many address ranges<br>
&gt; into one range.When a part of the big range needs<br>
&gt; to be changed,this will cause some innocent mappings<br>
&gt; to be unmapped.So we want to skip flatview_simplify().<br>
&gt; <br>
&gt; Signed-off-by: FelixCuioc &lt;<a href="mailto:FelixCui-oc@zhaoxin.com" target="_blank" rel="noreferrer">FelixCui-oc@zhaoxin.com</a>&gt;<br>
<br>
This has several issues.  In no particular order:<br>
<br>
1) you&#39;re adding host_get_vendor to target/i386/cpu.c so this does not<br>
even build for the default &quot;../configure &amp;&amp; make&quot;.<br>
<br>
2) you&#39;re adding a check for the host, but the bug applies to all hosts.<br>
 If there is a bug on x86 hardware emulation, it should be fixed even<br>
when emulating x86 from ARM.<br>
<br>
3) you&#39;re not explaining what is the big range and how the bug is<br>
manifesting.<br>
<br>
I think you&#39;re seeing issues when a guest accesses an adjacent mapping<br>
between the delete and add phases of the KVM MemoryListener.  We&#39;re<br>
considering fixing that in the kernel, by adding a new ioctl that<br>
changes the whole memory map in a single step.  I am CCing Peter Xu.<br>
<br>
Paolo<br>
<br>
<br>
&gt; ---<br>
&gt;  softmmu/memory.c  | 16 +++++++++++++++-<br>
&gt;  target/i386/cpu.c |  8 ++++++++<br>
&gt;  target/i386/cpu.h |  3 +++<br>
&gt;  3 files changed, 26 insertions(+), 1 deletion(-)<br>
&gt; <br>
&gt; diff --git a/softmmu/memory.c b/softmmu/memory.c<br>
&gt; index 70b93104e8..348e9db622 100644<br>
&gt; --- a/softmmu/memory.c<br>
&gt; +++ b/softmmu/memory.c<br>
&gt; @@ -699,6 +699,18 @@ static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)<br>
&gt;      return NULL;<br>
&gt;  }<br>
&gt;  <br>
&gt; +static bool skip_simplify(void)<br>
&gt; +{<br>
&gt; +    char vendor[CPUID_VENDOR_SZ + 1] = { 0 };<br>
&gt; +    host_get_vendor(vendor);<br>
&gt; +    if (!strncmp(vendor, CPUID_VENDOR_VIA, strlen(CPUID_VENDOR_VIA))<br>
&gt; +        || !strncmp(vendor, CPUID_VENDOR_ZHAOXIN,<br>
&gt; +                    strlen(CPUID_VENDOR_ZHAOXIN))) {<br>
&gt; +        return true;<br>
&gt; +    }<br>
&gt; +    return false;<br>
&gt; +}<br>
&gt; +<br>
&gt;  /* Render a memory topology into a list of disjoint absolute ranges. */<br>
&gt;  static FlatView *generate_memory_topology(MemoryRegion *mr)<br>
&gt;  {<br>
&gt; @@ -712,7 +724,9 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)<br>
&gt;                               addrrange_make(int128_zero(), int128_2_64()),<br>
&gt;                               false, false);<br>
&gt;      }<br>
&gt; -    flatview_simplify(view);<br>
&gt; +    if (!skip_simplify()) {<br>
&gt; +        flatview_simplify(view);<br>
&gt; +    }<br>
&gt;  <br>
&gt;      view-&gt;dispatch = address_space_dispatch_new(view);<br>
&gt;      for (i = 0; i &lt; view-&gt;nr; i++) {<br>
&gt; diff --git a/target/i386/cpu.c b/target/i386/cpu.c<br>
&gt; index 49d8958528..08508c8580 100644<br>
&gt; --- a/target/i386/cpu.c<br>
&gt; +++ b/target/i386/cpu.c<br>
&gt; @@ -1664,6 +1664,14 @@ void host_cpuid(uint32_t function, uint32_t count,<br>
&gt;          *edx = vec[3];<br>
&gt;  }<br>
&gt;  <br>
&gt; +void host_get_vendor(char *vendor)<br>
&gt; +{<br>
&gt; +    uint32_t eax, ebx, ecx, edx;<br>
&gt; +<br>
&gt; +    host_cpuid(0x0, 0, &amp;eax, &amp;ebx, &amp;ecx, &amp;edx);<br>
&gt; +    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);<br>
&gt; +}<br>
&gt; +<br>
&gt;  void host_vendor_fms(char *vendor, int *family, int *model, int *stepping)<br>
&gt;  {<br>
&gt;      uint32_t eax, ebx, ecx, edx;<br>
&gt; diff --git a/target/i386/cpu.h b/target/i386/cpu.h<br>
&gt; index d3097be6a5..14c8b4c09f 100644<br>
&gt; --- a/target/i386/cpu.h<br>
&gt; +++ b/target/i386/cpu.h<br>
&gt; @@ -832,6 +832,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];<br>
&gt;  <br>
&gt;  #define CPUID_VENDOR_VIA   &quot;CentaurHauls&quot;<br>
&gt;  <br>
&gt; +#define CPUID_VENDOR_ZHAOXIN   &quot;  Shanghai  &quot;<br>
&gt; +<br>
&gt;  #define CPUID_VENDOR_HYGON    &quot;HygonGenuine&quot;<br>
&gt;  <br>
&gt;  #define IS_INTEL_CPU(env) ((env)-&gt;cpuid_vendor1 == CPUID_VENDOR_INTEL_1 &amp;&amp; \<br>
&gt; @@ -1917,6 +1919,7 @@ void cpu_clear_apic_feature(CPUX86State *env);<br>
&gt;  void host_cpuid(uint32_t function, uint32_t count,<br>
&gt;                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);<br>
&gt;  void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);<br>
&gt; +void host_get_vendor(char *vendor);<br>
&gt;  <br>
&gt;  /* helper.c */<br>
&gt;  bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,<br>
&gt; <br>
<br>
</div>
</span></font></div>
</div>

</blockquote></div></div></div>
diff mbox series

Patch

diff --git a/softmmu/memory.c b/softmmu/memory.c
index 70b93104e8..348e9db622 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -699,6 +699,18 @@  static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
     return NULL;
 }
 
+static bool skip_simplify(void)
+{
+    char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
+    host_get_vendor(vendor);
+    if (!strncmp(vendor, CPUID_VENDOR_VIA, strlen(CPUID_VENDOR_VIA))
+        || !strncmp(vendor, CPUID_VENDOR_ZHAOXIN,
+                    strlen(CPUID_VENDOR_ZHAOXIN))) {
+        return true;
+    }
+    return false;
+}
+
 /* Render a memory topology into a list of disjoint absolute ranges. */
 static FlatView *generate_memory_topology(MemoryRegion *mr)
 {
@@ -712,7 +724,9 @@  static FlatView *generate_memory_topology(MemoryRegion *mr)
                              addrrange_make(int128_zero(), int128_2_64()),
                              false, false);
     }
-    flatview_simplify(view);
+    if (!skip_simplify()) {
+        flatview_simplify(view);
+    }
 
     view->dispatch = address_space_dispatch_new(view);
     for (i = 0; i < view->nr; i++) {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 49d8958528..08508c8580 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1664,6 +1664,14 @@  void host_cpuid(uint32_t function, uint32_t count,
         *edx = vec[3];
 }
 
+void host_get_vendor(char *vendor)
+{
+    uint32_t eax, ebx, ecx, edx;
+
+    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
+}
+
 void host_vendor_fms(char *vendor, int *family, int *model, int *stepping)
 {
     uint32_t eax, ebx, ecx, edx;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d3097be6a5..14c8b4c09f 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -832,6 +832,8 @@  typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 
 #define CPUID_VENDOR_VIA   "CentaurHauls"
 
+#define CPUID_VENDOR_ZHAOXIN   "  Shanghai  "
+
 #define CPUID_VENDOR_HYGON    "HygonGenuine"
 
 #define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \
@@ -1917,6 +1919,7 @@  void cpu_clear_apic_feature(CPUX86State *env);
 void host_cpuid(uint32_t function, uint32_t count,
                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
 void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);
+void host_get_vendor(char *vendor);
 
 /* helper.c */
 bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,