# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 833d05bdb4a49591928624517d0f496822a05c97
# Parent e913081f20f380c20e381deeb33d25232b36907c
[XEN] Fix compatibility with future guests which may try to
use hypercalls >= NR_hypercalls. These must fail with ENOSYS,
but the current strategy of masking off the high-order bits of
the hypercall number means we instead map those hypercalls onto
lower-numbered hypercalls with unpredictable results. This patch
replaces masking with an explicit compare-and-jump.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/x86_32/entry.S | 7 +++
xen/arch/x86/x86_64/entry.S | 10 +++--
xen/include/asm-ia64/config.h | 5 --
xen/include/asm-x86/config.h | 5 --
xen/include/asm-x86/multicall.h | 79 ++++++++++++++++++++++------------------
5 files changed, 58 insertions(+), 48 deletions(-)
diff -r e913081f20f3 -r 833d05bdb4a4 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S Tue Jun 13 10:14:20 2006 +0100
+++ b/xen/arch/x86/x86_32/entry.S Tue Jun 13 11:28:20 2006 +0100
@@ -171,7 +171,8 @@ ENTRY(hypercall)
SAVE_ALL(b)
sti
GET_CURRENT(%ebx)
- andl $(NR_hypercalls-1),%eax
+ cmpl $NR_hypercalls,%eax
+ jae bad_hypercall
PERFC_INCR(PERFC_hypercalls, %eax)
#ifndef NDEBUG
/* Deliberately corrupt parameter regs not used by this hypercall. */
@@ -260,6 +261,10 @@ process_nmi:
jmp test_all_events
1: bts $_VCPUF_nmi_pending,VCPU_flags(%ebx)
jmp test_guest_events
+
+bad_hypercall:
+ movl $-ENOSYS,UREGS_eax(%esp)
+ jmp test_all_events
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
/* {EIP, CS, EFLAGS, [ESP, SS]} */
diff -r e913081f20f3 -r 833d05bdb4a4 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S Tue Jun 13 10:14:20 2006 +0100
+++ b/xen/arch/x86/x86_64/entry.S Tue Jun 13 11:28:20 2006 +0100
@@ -130,7 +130,8 @@ ENTRY(syscall_enter)
/*hypercall:*/
movq %r10,%rcx
- andq $(NR_hypercalls-1),%rax
+ cmpq $NR_hypercalls,%rax
+ jae bad_hypercall
#ifndef NDEBUG
/* Deliberately corrupt parameter regs not used by this hypercall. */
pushq %rdi; pushq %rsi; pushq %rdx; pushq %rcx; pushq %r8 ; pushq %r9
@@ -142,7 +143,6 @@ ENTRY(syscall_enter)
rep stosq
popq %r9 ; popq %r8 ; popq %rcx; popq %rdx; popq %rsi; popq %rdi
movq UREGS_rax(%rsp),%rax
- andq $(NR_hypercalls-1),%rax
pushq %rax
pushq UREGS_rip+8(%rsp)
#endif
@@ -217,7 +217,11 @@ process_nmi:
jmp test_all_events
1: bts $_VCPUF_nmi_pending,VCPU_flags(%rbx)
jmp test_guest_events
-
+
+bad_hypercall:
+ movq $-ENOSYS,UREGS_rax(%rsp)
+ jmp test_all_events
+
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */
/* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
/* %rdx: trap_bounce, %rbx: struct vcpu */
diff -r e913081f20f3 -r 833d05bdb4a4 xen/include/asm-ia64/config.h
--- a/xen/include/asm-ia64/config.h Tue Jun 13 10:14:20 2006 +0100
+++ b/xen/include/asm-ia64/config.h Tue Jun 13 11:28:20 2006 +0100
@@ -97,12 +97,7 @@ extern char _end[]; /* standard ELF symb
//#define HZ 1000
// FIXME SMP: leave SMP for a later time
-/* A power-of-two value greater than or equal to number of hypercalls. */
#define NR_hypercalls 64
-
-#if NR_hypercalls & (NR_hypercalls - 1)
-#error "NR_hypercalls must be a power-of-two value"
-#endif
///////////////////////////////////////////////////////////////
// xen/include/asm/config.h
diff -r e913081f20f3 -r 833d05bdb4a4 xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h Tue Jun 13 10:14:20 2006 +0100
+++ b/xen/include/asm-x86/config.h Tue Jun 13 11:28:20 2006 +0100
@@ -63,12 +63,7 @@
name:
#endif
-/* A power-of-two value greater than or equal to number of hypercalls. */
#define NR_hypercalls 64
-
-#if NR_hypercalls & (NR_hypercalls - 1)
-#error "NR_hypercalls must be a power-of-two value"
-#endif
#ifndef NDEBUG
#define MEMORY_GUARD
diff -r e913081f20f3 -r 833d05bdb4a4 xen/include/asm-x86/multicall.h
--- a/xen/include/asm-x86/multicall.h Tue Jun 13 10:14:20 2006 +0100
+++ b/xen/include/asm-x86/multicall.h Tue Jun 13 11:28:20 2006 +0100
@@ -5,48 +5,59 @@
#ifndef __ASM_X86_MULTICALL_H__
#define __ASM_X86_MULTICALL_H__
+#include <xen/errno.h>
#include <asm/asm_defns.h>
#ifdef __x86_64__
-#define do_multicall_call(_call) \
- do { \
- __asm__ __volatile__ ( \
- "movq "STR(MULTICALL_op)"(%0),%%rax; " \
- "andq $("STR(NR_hypercalls)"-1),%%rax; " \
- "leaq "STR(hypercall_table)"(%%rip),%%rdi; "\
- "leaq (%%rdi,%%rax,8),%%rax; " \
- "movq "STR(MULTICALL_arg0)"(%0),%%rdi; " \
- "movq "STR(MULTICALL_arg1)"(%0),%%rsi; " \
- "movq "STR(MULTICALL_arg2)"(%0),%%rdx; " \
- "movq "STR(MULTICALL_arg3)"(%0),%%rcx; " \
- "movq "STR(MULTICALL_arg4)"(%0),%%r8; " \
- "callq *(%%rax); " \
- "movq %%rax,"STR(MULTICALL_result)"(%0); " \
- : : "b" (_call) \
- /* all the caller-saves registers */ \
- : "rax", "rcx", "rdx", "rsi", "rdi", \
- "r8", "r9", "r10", "r11" ); \
+#define do_multicall_call(_call) \
+ do { \
+ __asm__ __volatile__ ( \
+ " movq "STR(MULTICALL_op)"(%0),%%rax; " \
+ " cmpq $("STR(NR_hypercalls)"),%%rax; " \
+ " jae 2f; " \
+ " leaq "STR(hypercall_table)"(%%rip),%%rdi; "\
+ " leaq (%%rdi,%%rax,8),%%rax; " \
+ " movq "STR(MULTICALL_arg0)"(%0),%%rdi; " \
+ " movq "STR(MULTICALL_arg1)"(%0),%%rsi; " \
+ " movq "STR(MULTICALL_arg2)"(%0),%%rdx; " \
+ " movq "STR(MULTICALL_arg3)"(%0),%%rcx; " \
+ " movq "STR(MULTICALL_arg4)"(%0),%%r8; " \
+ " callq *(%%rax); " \
+ "1: movq %%rax,"STR(MULTICALL_result)"(%0)\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: movq $-"STR(ENOSYS)",%%rax\n" \
+ " jmp 1b\n" \
+ ".previous\n" \
+ : : "b" (_call) \
+ /* all the caller-saves registers */ \
+ : "rax", "rcx", "rdx", "rsi", "rdi", \
+ "r8", "r9", "r10", "r11" ); \
} while ( 0 )
#else
-#define do_multicall_call(_call) \
- do { \
- __asm__ __volatile__ ( \
- "pushl "STR(MULTICALL_arg4)"(%0); " \
- "pushl "STR(MULTICALL_arg3)"(%0); " \
- "pushl "STR(MULTICALL_arg2)"(%0); " \
- "pushl "STR(MULTICALL_arg1)"(%0); " \
- "pushl "STR(MULTICALL_arg0)"(%0); " \
- "movl "STR(MULTICALL_op)"(%0),%%eax; " \
- "andl $("STR(NR_hypercalls)"-1),%%eax; " \
- "call *hypercall_table(,%%eax,4); " \
- "movl %%eax,"STR(MULTICALL_result)"(%0); "\
- "addl $20,%%esp; " \
- : : "b" (_call) \
- /* all the caller-saves registers */ \
- : "eax", "ecx", "edx" ); \
+#define do_multicall_call(_call) \
+ do { \
+ __asm__ __volatile__ ( \
+ " pushl "STR(MULTICALL_arg4)"(%0); " \
+ " pushl "STR(MULTICALL_arg3)"(%0); " \
+ " pushl "STR(MULTICALL_arg2)"(%0); " \
+ " pushl "STR(MULTICALL_arg1)"(%0); " \
+ " pushl "STR(MULTICALL_arg0)"(%0); " \
+ " movl "STR(MULTICALL_op)"(%0),%%eax; " \
+ " cmpl $("STR(NR_hypercalls)"),%%eax; " \
+ " jae 2f; " \
+ " call *hypercall_table(,%%eax,4); " \
+ "1: movl %%eax,"STR(MULTICALL_result)"(%0); " \
+ " addl $20,%%esp\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: movl $-"STR(ENOSYS)",%%eax\n" \
+ " jmp 1b\n" \
+ ".previous\n" \
+ : : "b" (_call) \
+ /* all the caller-saves registers */ \
+ : "eax", "ecx", "edx" ); \
} while ( 0 )
#endif
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|