Skip to contentSkip to conversation

Use a status enum for reporting pass/fail

PATCH In review Bill Wendling 4 participants 15 messages Oct 12, 2019 – Oct 29, 2019

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/2 Use a status enum for reporting pass/fail

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Instead use a status enum so that the size of the argument no longer matters.

---
 lib/libcflat.h | 13 +++++++++++--
 lib/report.c   | 24 ++++++++++++------------
 2 files changed, 23 insertions(+), 14 deletions(-)
lib/libcflat.h +11 -2
index b6635d9..8f80a1c 100644
@@ -95,13 +95,22 @@ extern int vsnprintf(char *buf, int size, const char *fmt, va_list va)
 extern int vprintf(const char *fmt, va_list va)
 					__attribute__((format(printf, 1, 0)));
 
+enum status { PASSED, FAILED };
+
+#define STATUS(x) ((x) != 0 ? PASSED : FAILED)
+
+#define report(msg_fmt, status, ...) \
+	report_status(msg_fmt, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+#define report_xfail(msg_fmt, xfail, status, ...) \
+	report_xfail_status(msg_fmt, xfail, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+
 void report_prefix_pushf(const char *prefix_fmt, ...)
 					__attribute__((format(printf, 1, 2)));
 extern void report_prefix_push(const char *prefix);
 extern void report_prefix_pop(void);
-extern void report(const char *msg_fmt, unsigned pass, ...)
+extern void report_status(const char *msg_fmt, unsigned pass, ...)
 					__attribute__((format(printf, 1, 3)));
-extern void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+extern void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 					__attribute__((format(printf, 1, 4)));
 extern void report_abort(const char *msg_fmt, ...)
 					__attribute__((format(printf, 1, 2)))
lib/report.c +12 -12
index 2a5f549..4ba2ac0 100644
@@ -80,12 +80,12 @@ void report_prefix_pop(void)
 	spin_unlock(&lock);
 }
 
-static void va_report(const char *msg_fmt,
-		bool pass, bool xfail, bool skip, va_list va)
+static void va_report(const char *msg_fmt, enum status status, bool xfail,
+               bool skip, va_list va)
 {
 	const char *prefix = skip ? "SKIP"
-				  : xfail ? (pass ? "XPASS" : "XFAIL")
-					  : (pass ? "PASS"  : "FAIL");
+				  : xfail ? (status == PASSED ? "XPASS" : "XFAIL")
+					  : (status == PASSED ? "PASS"  : "FAIL");
 
 	spin_lock(&lock);
 
@@ -96,27 +96,27 @@ static void va_report(const char *msg_fmt,
 	puts("\n");
 	if (skip)
 		skipped++;
-	else if (xfail && !pass)
+	else if (xfail && status == FAILED)
 		xfailures++;
-	else if (xfail || !pass)
+	else if (xfail || status == FAILED)
 		failures++;
 
 	spin_unlock(&lock);
 }
 
-void report(const char *msg_fmt, unsigned pass, ...)
+void report_status(const char *msg_fmt, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, false, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, false, false, va);
 	va_end(va);
 }
 
-void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, xfail, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, xfail, false, va);
 	va_end(va);
 }
 
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
#1 lore raw

PATCH v2 2/2 x86: use pointer for end of exception table

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table.

---
 lib/x86/desc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
lib/x86/desc.c +2 -2
index 451f504..bfe8651 100644
@@ -41,7 +41,7 @@ struct ex_record {
     unsigned long handler;
 };
 
-extern struct ex_record exception_table_start, exception_table_end;
+extern struct ex_record exception_table_start, *exception_table_end;
 
 static const char* exception_mnemonic(int vector)
 {
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
 		(((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex != exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
#2 lore raw

PATCH 1/1 x86: use pointer for end of exception table

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table.

---
 lib/x86/desc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
lib/x86/desc.c +2 -2
index 451f504..cfc449f 100644
@@ -41,7 +41,7 @@ struct ex_record {
     unsigned long handler;
 };
 
-extern struct ex_record exception_table_start, exception_table_end;
+extern struct ex_record exception_table_start, *exception_table_end;
 
 static const char* exception_mnemonic(int vector)
 {
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
 		(((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex != (void*)&exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
#3 lore raw

Re: [kvm-unit-tests PATCH 1/1] x86: use pointer for end of exception table

Quoted 24 lines · Bill Wendling

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table.

---
 lib/x86/desc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
lib/x86/desc.c +1 -1
index 451f504..cfc449f 100644
@@ -41,7 +41,7 @@ struct ex_record {
     unsigned long handler;
 };
 
-extern struct ex_record exception_table_start, exception_table_end;
+extern struct ex_record exception_table_start, *exception_table_end;
 
 static const char* exception_mnemonic(int vector)
 {

lib/x86/desc.c static void check_exception_table(struct ex_regs *regs) · line 119

Quoted 8 lines
lib/x86/desc.c +1 -1
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
 		(((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex != (void*)&exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;

That looks like quite an ugly hack to me - and if clang gets a little bit smarter, I'm pretty sure it will optimize this away, too.

Could you please check if something like this works, too:

lib/x86/desc.c +2 -1
index 451f504..0e9779b 100644
@@ -41,7 +41,8 @@ struct ex_record {
     unsigned long handler;
 };
 
-extern struct ex_record exception_table_start, exception_table_end;
+extern struct ex_record exception_table_start;
+extern long exception_table_size;
 
 static const char* exception_mnemonic(int vector)
 {
@@ -108,12 +109,13 @@ static void check_exception_table(struct ex_regs

*regs)

 {
     struct ex_record *ex;
     unsigned ex_val;

+ int cnt = exception_table_size / sizeof(struct ex_record);

     ex_val = regs->vector | (regs->error_code << 16) |
                (((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));

- for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {

+    for (ex = &exception_table_start; cnt-- > 0; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
x86/flat.lds +1 -0
index a278b56..108fad5 100644
@@ -9,6 +9,7 @@ SECTIONS
           exception_table_start = .;
           *(.data.ex)
          exception_table_end = .;
+          exception_table_size = exception_table_end -
exception_table_start;
          }
     . = ALIGN(16);
     .rodata : { *(.rodata) }

Thomas

#4 lore raw

Re: [kvm-unit-tests PATCH 1/1] x86: use pointer for end of exception table

Quoted 28 lines · Thomas Huth
Quoted 26 lines · Bill Wendling

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table.

---
 lib/x86/desc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
lib/x86/desc.c +1 -1
index 451f504..cfc449f 100644
@@ -41,7 +41,7 @@ struct ex_record {
     unsigned long handler;
 };
 
-extern struct ex_record exception_table_start, exception_table_end;
+extern struct ex_record exception_table_start, *exception_table_end;
 
 static const char* exception_mnemonic(int vector)
 {
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
              (((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
Quoted 10 lines

lib/x86/desc.c static void check_exception_table(struct ex_regs *regs) · line 119

Quoted 6 lines
lib/x86/desc.c +1 -1
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex != (void*)&exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;

That looks like quite an ugly hack to me - and if clang gets a little bit smarter, I'm pretty sure it will optimize this away, too.

I agree. I was thinking about this actually and this patch looks like it'll work. I'll generate a new version of the patches.

lib/x86/desc.c +1 -1
index 451f504..4002203 100644
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
                (((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex < &exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
Quoted 47 lines

Could you please check if something like this works, too:

lib/x86/desc.c +4 -2
index 451f504..0e9779b 100644
@@ -41,7 +41,8 @@ struct ex_record {
     unsigned long handler;
 };
 
-extern struct ex_record exception_table_start, exception_table_end;
+extern struct ex_record exception_table_start;
+extern long exception_table_size;
 
 static const char* exception_mnemonic(int vector)
 {
@@ -108,12 +109,13 @@ static void check_exception_table(struct ex_regs
 *regs)
 {
     struct ex_record *ex;
     unsigned ex_val;
+    int cnt = exception_table_size / sizeof(struct ex_record);
 
     ex_val = regs->vector | (regs->error_code << 16) |
                (((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; cnt-- > 0; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
x86/flat.lds +1 -0
index a278b56..108fad5 100644
@@ -9,6 +9,7 @@ SECTIONS
           exception_table_start = .;
           *(.data.ex)
          exception_table_end = .;
+          exception_table_size = exception_table_end -
 exception_table_start;
          }
     . = ALIGN(16);
     .rodata : { *(.rodata) }

Thomas

#5 lore raw

PATCH v2 2/2 Use a status enum for reporting pass/fail

In reply to Bill Wendling

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Use instead a status enum so that the size of the argument no longer matters.

---
 lib/libcflat.h | 14 ++++++++++++--
 lib/report.c   | 24 ++++++++++++------------
 2 files changed, 24 insertions(+), 14 deletions(-)
lib/libcflat.h +12 -2
index b6635d9..847c24f 100644
@@ -95,13 +95,23 @@ extern int vsnprintf(char *buf, int size, const char *fmt, va_list va)
 extern int vprintf(const char *fmt, va_list va)
 					__attribute__((format(printf, 1, 0)));
 
+enum status { PASSED, FAILED };
+
+#define STATUS(x) ((x) != 0 ? PASSED : FAILED)
+
+#define VA_ARGS(...) , ##__VA_ARGS__
+#define report(msg_fmt, status, ...) \
+	report_status(msg_fmt, STATUS(status) VA_ARGS(__VA_ARGS__))
+#define report_xfail(msg_fmt, xfail, status, ...) \
+	report_xfail_status(msg_fmt, xfail, STATUS(status) VA_ARGS(__VA_ARGS__))
+
 void report_prefix_pushf(const char *prefix_fmt, ...)
 					__attribute__((format(printf, 1, 2)));
 extern void report_prefix_push(const char *prefix);
 extern void report_prefix_pop(void);
-extern void report(const char *msg_fmt, unsigned pass, ...)
+extern void report_status(const char *msg_fmt, unsigned pass, ...)
 					__attribute__((format(printf, 1, 3)));
-extern void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+extern void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 					__attribute__((format(printf, 1, 4)));
 extern void report_abort(const char *msg_fmt, ...)
 					__attribute__((format(printf, 1, 2)))
lib/report.c +12 -12
index 2a5f549..4ba2ac0 100644
@@ -80,12 +80,12 @@ void report_prefix_pop(void)
 	spin_unlock(&lock);
 }
 
-static void va_report(const char *msg_fmt,
-		bool pass, bool xfail, bool skip, va_list va)
+static void va_report(const char *msg_fmt, enum status status, bool xfail,
+               bool skip, va_list va)
 {
 	const char *prefix = skip ? "SKIP"
-				  : xfail ? (pass ? "XPASS" : "XFAIL")
-					  : (pass ? "PASS"  : "FAIL");
+				  : xfail ? (status == PASSED ? "XPASS" : "XFAIL")
+					  : (status == PASSED ? "PASS"  : "FAIL");
 
 	spin_lock(&lock);
 
@@ -96,27 +96,27 @@ static void va_report(const char *msg_fmt,
 	puts("\n");
 	if (skip)
 		skipped++;
-	else if (xfail && !pass)
+	else if (xfail && status == FAILED)
 		xfailures++;
-	else if (xfail || !pass)
+	else if (xfail || status == FAILED)
 		failures++;
 
 	spin_unlock(&lock);
 }
 
-void report(const char *msg_fmt, unsigned pass, ...)
+void report_status(const char *msg_fmt, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, false, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, false, false, va);
 	va_end(va);
 }
 
-void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, xfail, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, xfail, false, va);
 	va_end(va);
 }
 
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
#6 lore raw
In reply to Bill Wendling
Quoted 5 lines · Bill Wendling

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Instead use a status enum so that the size of the argument no longer matters.

The threading of these mails has me all kinds of confused. What is the relationship between all these patches? Did you perhaps intend to send some of these as v2?

[kvm-unit-tests PATCH 1/2] Use a status enum for reporting pass/fail [kvm-unit-tests PATCH 2/2] Use a status enum for reporting pass/fail [kvm-unit-tests PATCH 1/1] x86: use pointer for end of exception table [kvm-unit-tests PATCH 2/2] x86: use pointer for end of exception table

#7 lore raw
Quoted 8 lines · Sean Christopherson
Quoted 5 lines · Bill Wendling

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Instead use a status enum so that the size of the argument no longer matters.

Quoted 8 lines

The threading of these mails has me all kinds of confused. What is the relationship between all these patches? Did you perhaps intend to send some of these as v2?

[kvm-unit-tests PATCH 1/2] Use a status enum for reporting pass/fail [kvm-unit-tests PATCH 2/2] Use a status enum for reporting pass/fail [kvm-unit-tests PATCH 1/1] x86: use pointer for end of exception table [kvm-unit-tests PATCH 2/2] x86: use pointer for end of exception table

Yes, the later ones are meant as v2. I'm not familiar with the patch submission policy via emails. :-(

-bw

#8 lore raw

v2 cover Clang compilation fixes

In reply to Bill Wendling

The attached patches have fixes for clang compilation and some failures seen from the previous "report()" fix.

The first, changing the "report()" function to accept an "enum status" instead of "unsigned pass" is under discussion, with others making alternative suggestions. I add the patch here for completeness, but you may want to wait until the discussion has settled.

The second, using "less than" to compare two global objects' addresses for inequality, should be less controversial.

This replaces the previous two patches I sent. I apologize for the spammage.

[kvm-unit-tests PATCH 1/2] Use a status enum for reporting pass/fail [kvm-unit-tests PATCH 2/2] x86: use pointer for end of exception table

Bill Wendling (2):
lib: use a status enum for reporting pass/fail
x86: don't compare two global objects' addrs for inequality

 lib/libcflat.h | 13 +++++++++++--
 lib/report.c   | 24 ++++++++++++------------
 lib/x86/desc.c |  2 +-
 3 files changed, 24 insertions(+), 15 deletions(-)
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
#9 lore raw

PATCH v2 1/2 lib: use a status enum for reporting pass/fail

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Instead use a status enum so that the size of the argument no longer matters.

---
 lib/libcflat.h | 13 +++++++++++--
 lib/report.c   | 24 ++++++++++++------------
 2 files changed, 23 insertions(+), 14 deletions(-)
lib/libcflat.h +11 -2
index b6635d9..8765f67 100644
@@ -95,13 +95,22 @@ extern int vsnprintf(char *buf, int size, const char *fmt, va_list va)
 extern int vprintf(const char *fmt, va_list va)
 					__attribute__((format(printf, 1, 0)));
 
+enum status { PASSED, FAILED };
+
+#define STATUS(x) ((x) != 0 ? PASSED : FAILED)
+
+#define report(msg_fmt, status, ...) \
+	report_status(msg_fmt, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+#define report_xfail(msg_fmt, xfail, status, ...) \
+	report_xfail_status(msg_fmt, xfail, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+
 void report_prefix_pushf(const char *prefix_fmt, ...)
 					__attribute__((format(printf, 1, 2)));
 extern void report_prefix_push(const char *prefix);
 extern void report_prefix_pop(void);
-extern void report(const char *msg_fmt, unsigned pass, ...)
+extern void report_status(const char *msg_fmt, enum status status, ...)
 					__attribute__((format(printf, 1, 3)));
-extern void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+extern void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 					__attribute__((format(printf, 1, 4)));
 extern void report_abort(const char *msg_fmt, ...)
 					__attribute__((format(printf, 1, 2)))
lib/report.c +12 -12
index 2a5f549..4ba2ac0 100644
@@ -80,12 +80,12 @@ void report_prefix_pop(void)
 	spin_unlock(&lock);
 }
 
-static void va_report(const char *msg_fmt,
-		bool pass, bool xfail, bool skip, va_list va)
+static void va_report(const char *msg_fmt, enum status status, bool xfail,
+               bool skip, va_list va)
 {
 	const char *prefix = skip ? "SKIP"
-				  : xfail ? (pass ? "XPASS" : "XFAIL")
-					  : (pass ? "PASS"  : "FAIL");
+				  : xfail ? (status == PASSED ? "XPASS" : "XFAIL")
+					  : (status == PASSED ? "PASS"  : "FAIL");
 
 	spin_lock(&lock);
 
@@ -96,27 +96,27 @@ static void va_report(const char *msg_fmt,
 	puts("\n");
 	if (skip)
 		skipped++;
-	else if (xfail && !pass)
+	else if (xfail && status == FAILED)
 		xfailures++;
-	else if (xfail || !pass)
+	else if (xfail || status == FAILED)
 		failures++;
 
 	spin_unlock(&lock);
 }
 
-void report(const char *msg_fmt, unsigned pass, ...)
+void report_status(const char *msg_fmt, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, false, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, false, false, va);
 	va_end(va);
 }
 
-void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, xfail, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, xfail, false, va);
 	va_end(va);
 }
 
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
#10 lore raw

PATCH v2 2/2 x86: don't compare two global objects' addrs for inequality

In reply to Bill Wendling

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table. Avoid compariting inequality by using less-than.

---
 lib/x86/desc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/x86/desc.c +1 -1
index 451f504..4002203 100644
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
 		(((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex < &exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
Signature · 1 line
2.23.0.700.g56cf767bdb-goog
Reviewed-by on v2 2/2
#11 lore raw

Re: [kvm-unit-tests v2 PATCH 2/2] x86: don't compare two global objects' addrs for inequality

Quoted 15 lines · Bill Wendling

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table. Avoid compariting inequality by using less-than.

---
 lib/x86/desc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/x86/desc.c +0 -0
index 451f504..4002203 100644

lib/x86/desc.c static void check_exception_table(struct ex_regs *regs) · line 119

Quoted 8 lines
lib/x86/desc.c +1 -1
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
 		(((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex < &exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;
maintainer Applied
#12 lore raw

Re: [kvm-unit-tests v2 PATCH 2/2] x86: don't compare two global objects' addrs for inequality

In reply to Bill Wendling
Quoted 15 lines · Bill Wendling

Two global objects can't have the same address in C. Clang uses this fact to omit the check on the first iteration of the loop in check_exception_table. Avoid compariting inequality by using less-than.

---
 lib/x86/desc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/x86/desc.c +0 -0
index 451f504..4002203 100644

lib/x86/desc.c static void check_exception_table(struct ex_regs *regs) · line 119

Quoted 8 lines
lib/x86/desc.c +1 -1
@@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs)
 		(((regs->rflags >> 16) & 1) << 8);
     asm("mov %0, %%gs:4" : : "r"(ex_val));
 
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+    for (ex = &exception_table_start; ex < &exception_table_end; ++ex) {
         if (ex->rip == regs->rip) {
             regs->rip = ex->handler;
             return;

Queued, thanks.

Paolo

maintainer
#13 lore raw
In reply to Bill Wendling
Quoted 5 lines · Bill Wendling

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Instead use a status enum so that the size of the argument no longer matters.

I'm going to apply Thomas's argument reversal patch. Note that the commit message doesn't describe very well what is it that you're fixing (or rather, why it needs fixing).

Paolo

Quoted 92 lines
---
 lib/libcflat.h | 13 +++++++++++--
 lib/report.c   | 24 ++++++++++++------------
 2 files changed, 23 insertions(+), 14 deletions(-)
lib/libcflat.h +11 -2
index b6635d9..8f80a1c 100644
@@ -95,13 +95,22 @@ extern int vsnprintf(char *buf, int size, const char *fmt, va_list va)
 extern int vprintf(const char *fmt, va_list va)
 					__attribute__((format(printf, 1, 0)));
 
+enum status { PASSED, FAILED };
+
+#define STATUS(x) ((x) != 0 ? PASSED : FAILED)
+
+#define report(msg_fmt, status, ...) \
+	report_status(msg_fmt, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+#define report_xfail(msg_fmt, xfail, status, ...) \
+	report_xfail_status(msg_fmt, xfail, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+
 void report_prefix_pushf(const char *prefix_fmt, ...)
 					__attribute__((format(printf, 1, 2)));
 extern void report_prefix_push(const char *prefix);
 extern void report_prefix_pop(void);
-extern void report(const char *msg_fmt, unsigned pass, ...)
+extern void report_status(const char *msg_fmt, unsigned pass, ...)
 					__attribute__((format(printf, 1, 3)));
-extern void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+extern void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 					__attribute__((format(printf, 1, 4)));
 extern void report_abort(const char *msg_fmt, ...)
 					__attribute__((format(printf, 1, 2)))
lib/report.c +12 -12
index 2a5f549..4ba2ac0 100644
@@ -80,12 +80,12 @@ void report_prefix_pop(void)
 	spin_unlock(&lock);
 }
 
-static void va_report(const char *msg_fmt,
-		bool pass, bool xfail, bool skip, va_list va)
+static void va_report(const char *msg_fmt, enum status status, bool xfail,
+               bool skip, va_list va)
 {
 	const char *prefix = skip ? "SKIP"
-				  : xfail ? (pass ? "XPASS" : "XFAIL")
-					  : (pass ? "PASS"  : "FAIL");
+				  : xfail ? (status == PASSED ? "XPASS" : "XFAIL")
+					  : (status == PASSED ? "PASS"  : "FAIL");
 
 	spin_lock(&lock);
 
@@ -96,27 +96,27 @@ static void va_report(const char *msg_fmt,
 	puts("\n");
 	if (skip)
 		skipped++;
-	else if (xfail && !pass)
+	else if (xfail && status == FAILED)
 		xfailures++;
-	else if (xfail || !pass)
+	else if (xfail || status == FAILED)
 		failures++;
 
 	spin_unlock(&lock);
 }
 
-void report(const char *msg_fmt, unsigned pass, ...)
+void report_status(const char *msg_fmt, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, false, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, false, false, va);
 	va_end(va);
 }
 
-void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 {
 	va_list va;
-	va_start(va, pass);
-	va_report(msg_fmt, pass, xfail, false, va);
+	va_start(va, status);
+	va_report(msg_fmt, status, xfail, false, va);
 	va_end(va);
 }
 
#14 lore raw
Quoted 9 lines · Paolo Bonzini
Quoted 5 lines · Bill Wendling

Some values passed into "report" as "pass/fail" are larger than the size of the parameter. Instead use a status enum so that the size of the argument no longer matters.

I'm going to apply Thomas's argument reversal patch.

Okay.

Quoted 4 lines

Note that the
commit message doesn't describe very well what is it that you're fixing (or rather, why it needs fixing).

My apologies for that. I'll keep that in mind for future patches.

Quoted 95 lines

Paolo

Quoted 92 lines
---
 lib/libcflat.h | 13 +++++++++++--
 lib/report.c   | 24 ++++++++++++------------
 2 files changed, 23 insertions(+), 14 deletions(-)
lib/libcflat.h +11 -2
index b6635d9..8f80a1c 100644
@@ -95,13 +95,22 @@ extern int vsnprintf(char *buf, int size, const char *fmt, va_list va)
 extern int vprintf(const char *fmt, va_list va)
                                      __attribute__((format(printf, 1, 0)));
 
+enum status { PASSED, FAILED };
+
+#define STATUS(x) ((x) != 0 ? PASSED : FAILED)
+
+#define report(msg_fmt, status, ...) \
+     report_status(msg_fmt, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+#define report_xfail(msg_fmt, xfail, status, ...) \
+     report_xfail_status(msg_fmt, xfail, STATUS(status) __VA_OPT__(,) __VA_ARGS__)
+
 void report_prefix_pushf(const char *prefix_fmt, ...)
                                      __attribute__((format(printf, 1, 2)));
 extern void report_prefix_push(const char *prefix);
 extern void report_prefix_pop(void);
-extern void report(const char *msg_fmt, unsigned pass, ...)
+extern void report_status(const char *msg_fmt, unsigned pass, ...)
                                      __attribute__((format(printf, 1, 3)));
-extern void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+extern void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
                                      __attribute__((format(printf, 1, 4)));
 extern void report_abort(const char *msg_fmt, ...)
                                      __attribute__((format(printf, 1, 2)))
lib/report.c +12 -12
index 2a5f549..4ba2ac0 100644
@@ -80,12 +80,12 @@ void report_prefix_pop(void)
      spin_unlock(&lock);
 }
 
-static void va_report(const char *msg_fmt,
-             bool pass, bool xfail, bool skip, va_list va)
+static void va_report(const char *msg_fmt, enum status status, bool xfail,
+               bool skip, va_list va)
 {
      const char *prefix = skip ? "SKIP"
-                               : xfail ? (pass ? "XPASS" : "XFAIL")
-                                       : (pass ? "PASS"  : "FAIL");
+                               : xfail ? (status == PASSED ? "XPASS" : "XFAIL")
+                                       : (status == PASSED ? "PASS"  : "FAIL");
 
      spin_lock(&lock);
 
@@ -96,27 +96,27 @@ static void va_report(const char *msg_fmt,
      puts("\n");
      if (skip)
              skipped++;
-     else if (xfail && !pass)
+     else if (xfail && status == FAILED)
              xfailures++;
-     else if (xfail || !pass)
+     else if (xfail || status == FAILED)
              failures++;
 
      spin_unlock(&lock);
 }
 
-void report(const char *msg_fmt, unsigned pass, ...)
+void report_status(const char *msg_fmt, enum status status, ...)
 {
      va_list va;
-     va_start(va, pass);
-     va_report(msg_fmt, pass, false, false, va);
+     va_start(va, status);
+     va_report(msg_fmt, status, false, false, va);
      va_end(va);
 }
 
-void report_xfail(const char *msg_fmt, bool xfail, unsigned pass, ...)
+void report_xfail_status(const char *msg_fmt, bool xfail, enum status status, ...)
 {
      va_list va;
-     va_start(va, pass);
-     va_report(msg_fmt, pass, xfail, false, va);
+     va_start(va, status);
+     va_report(msg_fmt, status, xfail, false, va);
      va_end(va);
 }