Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fenv.feenableexcept_fegetexcept failed (x86_64 和 loongarch64 失败现场一致) #8

Open
oy456xd opened this issue Jan 24, 2024 · 2 comments

Comments

@oy456xd
Copy link

oy456xd commented Jan 24, 2024

larch the same error both in system and user mode

 ➜ /data/home/caiyinyu/qemu-2/build/qemu-loongarch64  out/target/product/generic_loongarch64/symbols/data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static --no_isolate  --gtest_filter=fenv.feenableexcept_fegetexcept
Note: Google Test filter = fenv.feenableexcept_fegetexcept
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from fenv
[ RUN      ] fenv.feenableexcept_fegetexcept
bionic/tests/utils.h:184: Failure
Value of: ((((status)+1) & 0x7f) >= 2)
  Actual: false
Expected: true
[  FAILED  ] fenv.feenableexcept_fegetexcept (6 ms)
[----------] 1 test from fenv (6 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (8 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] fenv.feenableexcept_fegetexcept

 1 FAILED TEST

x86_64

➜ qemu-x86_64 out/target/product/generic_x86_64/symbols/data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static --no_isolate  --gtest_filter=fenv.feenableexcept_fegetexcept
Note: Google Test filter = fenv.feenableexcept_fegetexcept
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from fenv
[ RUN      ] fenv.feenableexcept_fegetexcept
bionic/tests/utils.h:184: Failure
Value of: ((((status)+1) & 0x7f) >= 2)
 Actual: false
Expected: true
[  FAILED  ] fenv.feenableexcept_fegetexcept (20 ms)
[----------] 1 test from fenv (21 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (28 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] fenv.feenableexcept_fegetexcept

1 FAILED TEST

@oy456xd
Copy link
Author

oy456xd commented Jan 24, 2024

arm64 different from larch64 and x86_64

183 TEST(fenv, feenableexcept_fegetexcept) {
184 #if defined(__aarch64__) || defined(__arm__)
185   // ARM doesn't support this. They used to if you go back far enough, but it was removed in
186   // the Cortex-A8 between r3p1 and r3p2.                
187   ASSERT_EQ(-1, feenableexcept(FE_INVALID));             
188   ASSERT_EQ(0, fegetexcept());                           
189   ASSERT_EQ(-1, feenableexcept(FE_DIVBYZERO));
190   ASSERT_EQ(0, fegetexcept());
191   ASSERT_EQ(-1, feenableexcept(FE_OVERFLOW));
192   ASSERT_EQ(0, fegetexcept());
193   ASSERT_EQ(-1, feenableexcept(FE_UNDERFLOW));           
194   ASSERT_EQ(0, fegetexcept());
195   ASSERT_EQ(-1, feenableexcept(FE_INEXACT));
196   ASSERT_EQ(0, fegetexcept());                           
197   ASSERT_EQ(-1, feenableexcept(FE_DENORMAL));                             
198   ASSERT_EQ(0, fegetexcept());                           
199 #else             
200   // We can't recover from SIGFPE, so sacrifice a child...
201   pid_t pid = fork();
202   ASSERT_NE(-1, pid) << strerror(errno);                 
203                   
204   if (pid == 0) { 
205     signal(SIGFPE, SIG_DFL);  // Disable debuggerd.      
206     feclearexcept(FE_ALL_EXCEPT);
207     ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
208     ASSERT_EQ(0, feenableexcept(FE_INVALID));            
209     ASSERT_EQ(FE_INVALID, fegetexcept());                
210     ASSERT_EQ(0, feraiseexcept(FE_INVALID));             
211     _exit(123);   
212   }               
213                   
214   AssertChildExited(pid, -SIGFPE);
215 #endif            
216 }                 

@oy456xd
Copy link
Author

oy456xd commented Feb 28, 2024

fenv.feenableexcept_fegetexcept should be tested on a real machine.

The expected behavior of the child process is to receive the SIGFPE signal(hardware trapping of floating point exceptions) and terminate accordingly upon executing line 217 (something like the following). This enables the parent process to identify the termination signal, allowing the test to pass successfully.

(gdb) 

Thread 2.1 "a.out" received signal SIGFPE, Arithmetic exception.
0x00007ffff287d4e8 in feraiseexcept () from /lib/loongarch64-linux-gnu/libm.so.6
=> 0x00007ffff287d4e8 <feraiseexcept+12>:	01068420	fdiv.s      	$fa0, $fa1, $fa1
(gdb) 
Single stepping until exit from function feraiseexcept,
which has no line number information.

Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.
Child process terminated due to SIGFPE (Floating point exception), status is 8

LoongArch supports hardware trapping of floating point exceptions.
when testing with qemu, the fcsr Enables field has been set correctly and the child process should terminate upon executing feraiseexcept(FE_INVALID), however, it just set the fcsr Flags field and _exit(123);, so the test failed.

See:

(gdb) list 
213	    feclearexcept(FE_ALL_EXCEPT);
214	    ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
215	    ASSERT_EQ(0, feenableexcept(FE_INVALID));
216	    ASSERT_EQ(FE_INVALID, fegetexcept());
217	    ASSERT_EQ(0, feraiseexcept(FE_INVALID));
218	    _exit(123);
219	  }
220	  pid_t pid_o = getpid();
221	  std::cout << "The out process's PID_o is: " << pid_o << std::endl;
222	
(gdb) 
223	  AssertChildExited(pid, -SIGFPE);
224	#endif
225	}
(gdb) f
#0  fenv_feenableexcept_fegetexcept_Test::TestBody (this=<optimized out>) at bionic/tests/fenv_test.cpp:218
218	    _exit(123);
=> 0x0000000120174718 <_ZN36fenv_feenableexcept_fegetexcept_Test8TestBodyEv+2816>:	1e0002e1	pcaddu18i   	$ra, 23
   0x000000012017471c <_ZN36fenv_feenableexcept_fegetexcept_Test8TestBodyEv+2820>:	4c91c821	jirl        	$ra, $ra, 37320
(gdb) i registers fcsr 
fcsr           0x100010            1048592
(gdb) 

Reference:
https://loongson.github.io/LoongArch-Documentation/README-CN.html
龙芯架构参考手册 - 卷一:基础架构: 该手册介绍了龙芯架构中基础架构部分的内容。
LoongArch-Vol1-v1.10-CN.pdf

tst code:

# caiyinyu @ 3D-debian12 loongarch64 10.40.65.51 1 in ~/kernel_common on git: a12_larch [10:54:11] 
  ➜ bear -- gcc -g tmp-fe.c -lm -D_GNU_SOURCE

  ➜ cat tmp-fe.c         
#include <stdio.h>
#include <stdlib.h>
#include <fenv.h>
#include <unistd.h>
#include <sys/wait.h>

#pragma STDC FENV_ACCESS ON

int main()
{
	pid_t pid = fork();

	if (pid == -1) {
		perror("fork failed");
		exit(EXIT_FAILURE);
	} else if (pid > 0) {
		// 父进程
		int status;
		waitpid(pid, &status, 0); // 等待子进程结束
		int signal_num = WTERMSIG(status);
		if (signal_num == SIGFPE) {
			printf("Child process terminated due to SIGFPE (Floating point exception), status is %d\n",
			       status);
		} else if (WIFEXITED(status)) {
			printf("Child process exited with status %d\n",
			       WEXITSTATUS(status));
		}
	} else {
		// 子进程
		feclearexcept(FE_ALL_EXCEPT); // 清除所有的浮点异常标志

		// set Enables field(fcsr1), allow traping,  See LoongArch-Vol1-v1.10-CN.pdf
		feenableexcept(FE_INVALID);

		feraiseexcept(FE_INVALID); // 引发FE_INVALID异常, trap

		// remove feenableexcept(FE_INVALID) to run the following.
		printf("-------------------\n");

		if (fetestexcept(FE_INVALID)) { // 检查FE_INVALID异常是否被设置
			printf("FE_INVALID exception raised\n");
		}

		/* _exit(8); */
		_exit(EXIT_SUCCESS);
	}

	return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant