On Tue, Dec 15, 2015 at 2:25 AM, Paolo Bonzini <[email protected]> wrote:
> Test functions know whether an exception was generated simply by checking
> the last value returned by set_exception_jmpbuf. The exception number is
> passed to set_exception_jmpbuf so that it can set up the exception handler.
I like the idea of test_for_exception, it makes the unit tests simpler. But
this (and the previous) version, require the trigger function to be in on
the joke (either by it calling set_exception_return, or now by it calling
set_exception_jmpbuf and handle_exception(NULL)).
What do you think about this simplification?
bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data),
void *data)
jmp_buf jmpbuf;
int ret;
handle_exception(ex, exception_handler);
ret = set_exception_jmpbuf(&jmpbuf);
if (ret == 0)
trigger_func(data);
handle_exception(ex, NULL);
return ret;
}
Then trigger_func can be very simple, e.g.
static void do_write_apicbase(u64 data)
{
wrmsr(MSR_IA32_APICBASE, data);
}
>
> Signed-off-by: Paolo Bonzini <[email protected]>
> ---
> lib/x86/desc.c | 13 +------------
> lib/x86/desc.h | 8 +++-----
> x86/apic.c | 34 +++++++++++++++++-----------------
> x86/vmx.c | 29 +++++++++++++++++++----------
> 4 files changed, 40 insertions(+), 44 deletions(-)
>
> diff --git a/lib/x86/desc.c b/lib/x86/desc.c
> index acf29e3..acf66b6 100644
> --- a/lib/x86/desc.c
> +++ b/lib/x86/desc.c
> @@ -315,7 +315,6 @@ void setup_alt_stack(void)
> }
> #endif
>
> -static bool exception;
> static jmp_buf *exception_jmpbuf;
>
> static void exception_handler_longjmp(void)
> @@ -326,21 +325,11 @@ static void exception_handler_longjmp(void)
> static void exception_handler(struct ex_regs *regs)
> {
> /* longjmp must happen after iret, so do not do it now. */
> - exception = true;
> regs->rip = (unsigned long)&exception_handler_longjmp;
> }
>
> -bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data),
> - void *data)
> +void __set_exception_jmpbuf(unsigned int ex, jmp_buf *addr)
> {
> handle_exception(ex, exception_handler);
> - exception = false;
> - trigger_func(data);
> - handle_exception(ex, NULL);
> - return exception;
> -}
> -
> -void __set_exception_jmpbuf(jmp_buf *addr)
> -{
> exception_jmpbuf = addr;
> }
> diff --git a/lib/x86/desc.h b/lib/x86/desc.h
> index be52fd4..fceabd8 100644
> --- a/lib/x86/desc.h
> +++ b/lib/x86/desc.h
> @@ -155,10 +155,8 @@ void set_intr_alt_stack(int e, void *fn);
> void print_current_tss_info(void);
> void handle_exception(u8 v, void (*func)(struct ex_regs *regs));
>
> -bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data),
> - void *data);
> -void __set_exception_jmpbuf(jmp_buf *addr);
> -#define set_exception_jmpbuf(jmpbuf) \
> - (setjmp(jmpbuf) ? : (__set_exception_jmpbuf(&(jmpbuf)), 0))
> +void __set_exception_jmpbuf(unsigned int ex, jmp_buf *addr);
> +#define set_exception_jmpbuf(ex, jmpbuf) \
> + (setjmp(jmpbuf) ? : (__set_exception_jmpbuf((ex), &(jmpbuf)), 0))
>
> #endif
> diff --git a/x86/apic.c b/x86/apic.c
> index 2e04c82..de19724 100644
> --- a/x86/apic.c
> +++ b/x86/apic.c
> @@ -61,12 +61,18 @@ static void test_tsc_deadline_timer(void)
> }
> }
>
> -static void do_write_apicbase(void *data)
> +static bool do_write_apicbase(u64 data)
> {
> jmp_buf jmpbuf;
> - if (set_exception_jmpbuf(jmpbuf) == 0) {
> - wrmsr(MSR_IA32_APICBASE, *(u64 *)data);
> + int ret;
> + if (set_exception_jmpbuf(GP_VECTOR, jmpbuf) == 0) {
> + wrmsr(MSR_IA32_APICBASE, data);
> + ret = 0;
> + } else {
> + ret = 1;
> }
> + handle_exception(GP_VECTOR, NULL);
> + return ret;
> }
>
> void test_enable_x2apic(void)
> @@ -80,24 +86,19 @@ void test_enable_x2apic(void)
> printf("x2apic enabled\n");
>
> report("x2apic enabled to invalid state",
> - test_for_exception(GP_VECTOR, do_write_apicbase,
> - &invalid_state));
> + do_write_apicbase(invalid_state));
> report("x2apic enabled to apic enabled",
> - test_for_exception(GP_VECTOR, do_write_apicbase,
> - &apic_enabled));
> + do_write_apicbase(apic_enabled));
>
> wrmsr(MSR_IA32_APICBASE, APIC_DEFAULT_PHYS_BASE | APIC_BSP);
> report("disabled to invalid state",
> - test_for_exception(GP_VECTOR, do_write_apicbase,
> - &invalid_state));
> + do_write_apicbase(invalid_state));
> report("disabled to x2apic enabled",
> - test_for_exception(GP_VECTOR, do_write_apicbase,
> - &x2apic_enabled));
> + do_write_apicbase(x2apic_enabled));
>
> wrmsr(MSR_IA32_APICBASE, apic_enabled);
> report("apic enabled to invalid state",
> - test_for_exception(GP_VECTOR, do_write_apicbase,
> - &invalid_state));
> + do_write_apicbase(invalid_state));
>
> wrmsr(MSR_IA32_APICBASE, x2apic_enabled);
> apic_write(APIC_SPIV, 0x1ff);
> @@ -105,8 +106,7 @@ void test_enable_x2apic(void)
> printf("x2apic not detected\n");
>
> report("enable unsupported x2apic",
> - test_for_exception(GP_VECTOR, do_write_apicbase,
> - &x2apic_enabled));
> + do_write_apicbase(x2apic_enabled));
> }
> }
>
> @@ -128,11 +128,11 @@ static void test_apicbase(void)
>
> value = orig_apicbase | (1UL << cpuid_maxphyaddr());
> report("reserved physaddr bits",
> - test_for_exception(GP_VECTOR, do_write_apicbase, &value));
> + do_write_apicbase(value));
>
> value = orig_apicbase | 1;
> report("reserved low bits",
> - test_for_exception(GP_VECTOR, do_write_apicbase, &value));
> + do_write_apicbase(value));
>
> wrmsr(MSR_IA32_APICBASE, orig_apicbase);
> apic_write(APIC_SPIV, 0x1ff);
> diff --git a/x86/vmx.c b/x86/vmx.c
> index ee9aca8..0b2cce0 100644
> --- a/x86/vmx.c
> +++ b/x86/vmx.c
> @@ -617,21 +617,33 @@ static void init_vmx(void)
> memset(guest_syscall_stack, 0, PAGE_SIZE);
> }
>
> -static void do_vmxon_off(void *data)
> +static bool do_vmxon_off(void)
> {
> jmp_buf jmpbuf;
> - if (set_exception_jmpbuf(jmpbuf) == 0) {
> + bool ret;
> + if (set_exception_jmpbuf(GP_VECTOR, jmpbuf) == 0) {
> vmx_on();
> vmx_off();
> + return 0;
> + } else {
> + return 1;
> }
> + handle_exception(GP_VECTOR, NULL);
> + return ret;
> }
>
> -static void do_write_feature_control(void *data)
> +static bool do_write_feature_control(void)
> {
> jmp_buf jmpbuf;
> - if (set_exception_jmpbuf(jmpbuf) == 0) {
> + bool ret;
> + if (set_exception_jmpbuf(GP_VECTOR, jmpbuf) == 0) {
> wrmsr(MSR_IA32_FEATURE_CONTROL, 0);
> + ret = 0;
> + } else {
> + ret = 1;
> }
> + handle_exception(GP_VECTOR, NULL);
> + return ret;
> }
>
> static int test_vmx_feature_control(void)
> @@ -650,19 +662,16 @@ static int test_vmx_feature_control(void)
> }
>
> wrmsr(MSR_IA32_FEATURE_CONTROL, 0);
> - report("test vmxon with FEATURE_CONTROL cleared",
> - test_for_exception(GP_VECTOR, &do_vmxon_off, NULL));
> + report("test vmxon with FEATURE_CONTROL cleared", do_vmxon_off());
>
> wrmsr(MSR_IA32_FEATURE_CONTROL, 0x4);
> - report("test vmxon without FEATURE_CONTROL lock",
> - test_for_exception(GP_VECTOR, &do_vmxon_off, NULL));
> + report("test vmxon without FEATURE_CONTROL lock", do_vmxon_off());
>
> wrmsr(MSR_IA32_FEATURE_CONTROL, 0x5);
> vmx_enabled = ((rdmsr(MSR_IA32_FEATURE_CONTROL) & 0x5) == 0x5);
> report("test enable VMX in FEATURE_CONTROL", vmx_enabled);
>
> - report("test FEATURE_CONTROL lock bit",
> - test_for_exception(GP_VECTOR, &do_write_feature_control,
> NULL));
> + report("test FEATURE_CONTROL lock bit", do_write_feature_control());
>
> return !vmx_enabled;
> }
> --
> 2.5.0
>
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html