Bug 207173

Summary: kvm compiling problem 5.6.x kvm_main.c:2236:42: error: ‘nr_pages_avail’ may be used uninitialized in this function
Product: Virtualization Reporter: zoran.davidovac
Component: kvmAssignee: virtualization_kvm
Status: NEW ---    
Severity: enhancement CC: euloanty, mike.auty, seanjc, ticat_fp, tony-cook
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: linux-5.6.-linux-5.6.3 Subsystem:
Regression: No Bisected commit-id:

Description zoran.davidovac 2020-04-09 14:25:44 UTC
happens with stock kernel 5.6.x gcc version 9.3.0 (GCC) 


  CC      arch/x86/kvm/../../../virt/kvm/kvm_main.o
arch/x86/kvm/../../../virt/kvm/kvm_main.c: In function ‘__kvm_gfn_to_hva_cache_init’:
arch/x86/kvm/../../../virt/kvm/kvm_main.c:2236:42: error: ‘nr_pages_avail’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 2236 |  for ( ; start_gfn <= end_gfn; start_gfn += nr_pages_avail) {
      |                                ~~~~~~~~~~^~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[2]: *** [scripts/Makefile.build:268: arch/x86/kvm/../../../virt/kvm/kvm_main.o] Error 1
make[1]: *** [scripts/Makefile.build:505: arch/x86/kvm] Error 2
make: *** [Makefile:1683: arch/x86] Error 2

Waited till .3 and I am still surprised that nobody noticed :)
Comment 1 ticat 2020-04-12 07:28:32 UTC
I don't think it's a problem or bug.Why?
If program executes this for()-statement,that's start_gfn >= end_gfn.
"start_gfn += nr_pages_avail" first is executed when for-body's end,so for nr_pages_avail, it's OKAY.
Comment 2 Sean Christopherson 2020-04-13 23:41:40 UTC
Is this reproducible on all 5.6.x releases?  Just want to double check that something didn't change between 5.6 and 5.6.3 that somehow broke things.

Can you attach your config?  This has been reported before[*], but only with a proprietary compiler.  Maybe the issue is dependent on the config more so than the compiler.

https://lkml.kernel.org/r/20200218184756.242904-1-oupton@google.com
Comment 3 zoran.davidovac 2020-04-14 09:19:13 UTC
Yes all 5.6.X (up to 4 tested) before it was while loop now there is for loop
and some other changes in kvm code vs 5.5.x kernel that compiles with same code,
and yes always reproducible.

Standard gcc 9.2 now 9.3

https://drive.google.com/open?id=18NDMqounXy6RwNhRxTJDUizTckm7QBOR
I do not see any other way to add file except paste it encode it ?

# make bzImage
  CALL    scripts/checksyscalls.sh
  CALL    scripts/atomic/check-atomics.sh
  DESCEND  objtool
  CHK     include/generated/compile.h
  CC      arch/x86/kvm/../../../virt/kvm/kvm_main.o
arch/x86/kvm/../../../virt/kvm/kvm_main.c: In function ‘__kvm_gfn_to_hva_cache_init’:
arch/x86/kvm/../../../virt/kvm/kvm_main.c:2236:42: error: ‘nr_pages_avail’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 2236 |  for ( ; start_gfn <= end_gfn; start_gfn += nr_pages_avail) {
      |                                ~~~~~~~~~~^~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[2]: *** [scripts/Makefile.build:268: arch/x86/kvm/../../../virt/kvm/kvm_main.o] Error 1
make[1]: *** [scripts/Makefile.build:505: arch/x86/kvm] Error 2
make: *** [Makefile:1683: arch/x86] Error 2
root@host:/usr/src/linux-5.6.4#
Comment 4 Sean Christopherson 2020-04-14 15:37:27 UTC
Hrm, still can't reproduce this even with your config and gcc 9.2.  Can you paste the build command for kvm_main.o?  It should be the first line in virt/kvm/.kvm_main.o.cmd in your build directory, e.g.

cmd_arch/x86/kvm/../../../virt/kvm/kvm_main.o := /usr/bin/gcc-9 -Wp,-MD,arch/x86/kvm/../../../virt/kvm/.kvm_main.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/9/include -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -march=core2 -mno-red-zone -mcmodel=kernel -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_AVX512=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -DCONFIG_AS_ADX=1 -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 --param=allow-store-data-races=0 -fstack-protector-strong -Wno-unused-but-set-variable -Wimplicit-fallthrough -Wno-unused-const-variable -fomit-frame-pointer -fno-var-tracking-assignments -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -fmacro-prefix-map=./= -fcf-protection=none -Wno-packed-not-aligned -Iarch/x86/kvm -Werror -I ./arch/x86/kvm -I ./arch/x86/kvm    -DKBUILD_MODFILE='"arch/x86/kvm/kvm"' -DKBUILD_BASENAME='"kvm_main"' -DKBUILD_MODNAME='"kvm"' -c -o arch/x86/kvm/../../../virt/kvm/kvm_main.o ./arch/x86/kvm/../../../virt/kvm/kvm_main.c
Comment 5 zoran.davidovac 2020-04-14 18:53:49 UTC
I've back-ported kvm and instead loop changed to while as in 5.4 
and I could compile it.

But I found what the problem is. 

In short I can compile it with -O2 , -O2 -march=native, but NOT with -O3 with or without -march=native.
Further more in kernel menuconfig optimization I see only O2 an Os(ize) now!?

How to reproduce:
-use my config
-edit Makefile and replace -O2 to -O3 and you will get this error.


I always compile stock kernel with -O3 -march=native for servers 
and my laptop with -Ofast -march=native for ages without any problem :)

On error .kvm_main.o.cmd is not generated, thank you Sean, 
you made me look to something that I would never suspect
as I had same compile problem on server, laptop and virtual server.
Comment 6 Sean Christopherson 2020-04-15 01:19:32 UTC
Ah, fun.  So this falls into the "not technically a kernel problem" category.  O3 isn't supported outside of the ARC architecture (no clue why it "needs" O3), and AFAICT, has never been a selectable Kconfig option outside of ARC.

The false positives with -Wmaybe-uninitialized and -O3 (and -Os) is a known issue, e.g. the kernel adds -Wno-maybe-uninitialized when compiling with either of those options.  Unfortunately, there is no direct way to force CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED=y.  You could select CONFIG_CC_OPTIMIZE_FOR_SIZE and then edit your Makefile, but I think that might have unwanted side effects.

The easiest way to workaround this issue is to do CONFIG_KVM_WERROR=n.  The false positive warning will still occur, but it won't get escalated to an error and break your build.  I'm guessing there's a way to get -Wno-maybe-uninitialized, but disabling -Werror for KVM is easy and doesn't really have downsides.
Comment 7 zoran.davidovac 2020-04-15 05:43:31 UTC
Interesting, 

I did not know that -O3 is not supported on x86 or x86_64,
in kernel Doc it does not say it is not supported and
It worked very well until now :)

So this happen also to size optimized kernel?

But now I also know why O3 is disabled in menuconfig :)

KBUILD_CFLAGS += -O2
else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
KBUILD_CFLAGS += -O3
else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os
endif

I've read somewhere that on arm -O3 is related to implicit parallelism 

Changed category to enhancement, let me know if I need to change anything else?

thx.
Comment 8 cqwrteur 2020-04-26 02:10:31 UTC
I have found out a solution:

change line 2160:

gfn_t nr_pages_avail;

to line 2160.

Just initialize it.

gfn_t nr_pages_avail=0;

done
Comment 9 Sean Christopherson 2020-04-27 16:45:45 UTC
Zeroing nr_pages_avail was proposed upstream[*] and effectively rejected because it's unnecessary, i.e. there is no KVM bug.

[*] https://lkml.kernel.org/r/20200218184756.242904-1-oupton@google.com
Comment 10 Tony Cook 2020-05-10 02:04:46 UTC
arch/x86/kvm/../../../virt/kvm/kvm_main.c: In function ‘__kvm_gfn_to_hva_cache_init’:
arch/x86/kvm/../../../virt/kvm/kvm_main.c:2236:42: error: ‘nr_pages_avail’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 2236 |  for ( ; start_gfn <= end_gfn; start_gfn += nr_pages_avail) {
cc1: all warnings being treated as errors
make[2]: *** [scripts/Makefile.build:267: arch/x86/kvm/../../../virt/kvm/kvm_main.o] Error 1
make[1]: *** [scripts/Makefile.build:505: arch/x86/kvm] Error 2
make[1]: *** Waiting for unfinished jobs....

Nothing non-standard here, just trying to build the latest kernel 5.6.11 with # Compiler: gcc (GCC) 10.0.1 20200430 (Red Hat 10.0.1-0.14)

I agree that there is in fact no error here as the nr_pages_avail is set before it is used to increment start_gfn, or at any rate one can infer that it might be set by the procedure call that passes it by reference. Nonetheless it is more than just annoying when this breaks my build. Either change the default setting and disable werror for this module or make the uneccessary assignment just for my pleasure.
Comment 11 Mike Auty 2020-05-12 10:30:30 UTC
I'm also experiencing this, but not on clang, on gcc-10.1.0.  The initially proposed resolution:

gfn_t nr_pages_avail = 0; 

succeeded.  The alternative resolution:

gfn uninitialized_var(nr_pages_avail);

Needed to be changed to 

gfn_t uninitialized_var(nr_pages_avail);

but also allowed compilation.

The suggestion to mark __gfn_to_hva_many and gfn_to_hva_many as always inline failed to resolve the problem though.
Comment 12 Sean Christopherson 2020-05-12 14:37:10 UTC
This is "fixed" in upstream (for kernel 5.7) by commit 78a5255ffb6a1 ("Stop the ad-hoc games with -Wno-maybe-initialized").