x86/entry: Remove support for partial cpu_user_regs frames

Save all GPRs on entry to Xen.

The entry_int82() path is via a DPL1 gate, only usable by 32bit PV guests, so
can get away with only saving the 32bit registers.  All other entrypoints can
be reached from 32 or 64bit contexts.

This is part of XSA-254.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2018-01-05 19:57:07 +00:00
1 parent b357546b43
commit f9eb74789a
10 files changed
+26 -125

No files matched your search

-1
View File
@@ -3,7 +3,6 @@
#include <sys/mman.h>
#define cpu_has_amd_erratum(nr) 0
#define mark_regs_dirty(r) ((void)(r))
#define cpu_has_mpx false
#define read_bndcfgu() 0
#define xstate_set_init(what)
-1
View File
@@ -20,7 +20,6 @@
static void noreturn continue_nonidle_domain(struct vcpu *v)
{
check_wakeup_from_wait();
mark_regs_dirty(guest_cpu_user_regs());
reset_stack_and_jump(ret_from_intr);
}
-2
View File
@@ -337,7 +337,6 @@ static int read_io(unsigned int port, unsigned int bytes,
io_emul_stub_t *io_emul =
io_emul_stub_setup(poc, ctxt->opcode, port, bytes);
mark_regs_dirty(ctxt->regs);
io_emul(ctxt->regs);
return X86EMUL_DONE;
}
@@ -436,7 +435,6 @@ static int write_io(unsigned int port, unsigned int bytes,
io_emul_stub_t *io_emul =
io_emul_stub_setup(poc, ctxt->opcode, port, bytes);
mark_regs_dirty(ctxt->regs);
io_emul(ctxt->regs);
if ( (bytes == 1) && pv_post_outb_hook )
pv_post_outb_hook(port, val);
+4 -3
View File
@@ -16,7 +16,8 @@
ENTRY(entry_int82)
ASM_CLAC
pushq $0
SAVE_VOLATILE type=HYPERCALL_VECTOR compat=1
movl $HYPERCALL_VECTOR, 4(%rsp)
SAVE_ALL compat=1 /* DPL1 gate, restricted to 32bit PV guests only. */
CR4_PV32_RESTORE
GET_CURRENT(bx)
@@ -60,7 +61,6 @@ compat_test_guest_events:
/* %rbx: struct vcpu */
compat_process_softirqs:
sti
andl $~TRAP_regs_partial,UREGS_entry_vector(%rsp)
call do_softirq
jmp compat_test_all_events
@@ -197,7 +197,8 @@ ENTRY(cstar_enter)
pushq $FLAT_USER_CS32
pushq %rcx
pushq $0
SAVE_VOLATILE TRAP_syscall
movl $TRAP_syscall, 4(%rsp)
SAVE_ALL
GET_CURRENT(bx)
movq VCPU_domain(%rbx),%rcx
cmpb $0,DOMAIN_is_32bit_pv(%rcx)
+6 -6
View File
@@ -98,7 +98,8 @@ ENTRY(lstar_enter)
pushq $FLAT_KERNEL_CS64
pushq %rcx
pushq $0
SAVE_VOLATILE TRAP_syscall
movl $TRAP_syscall, 4(%rsp)
SAVE_ALL
GET_CURRENT(bx)
testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
jz switch_to_kernel
@@ -140,7 +141,6 @@ test_guest_events:
/* %rbx: struct vcpu */
process_softirqs:
sti
SAVE_PRESERVED
call do_softirq
jmp test_all_events
@@ -190,7 +190,8 @@ GLOBAL(sysenter_eflags_saved)
pushq $3 /* ring 3 null cs */
pushq $0 /* null rip */
pushq $0
SAVE_VOLATILE TRAP_syscall
movl $TRAP_syscall, 4(%rsp)
SAVE_ALL
GET_CURRENT(bx)
cmpb $0,VCPU_sysenter_disables_events(%rbx)
movq VCPU_sysenter_addr(%rbx),%rax
@@ -207,7 +208,6 @@ UNLIKELY_END(sysenter_nt_set)
leal (,%rcx,TBF_INTERRUPT),%ecx
UNLIKELY_START(z, sysenter_gpf)
movq VCPU_trap_ctxt(%rbx),%rsi
SAVE_PRESERVED
movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
movl %eax,TRAPBOUNCE_error_code(%rdx)
movq TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rsi),%rax
@@ -225,7 +225,8 @@ UNLIKELY_END(sysenter_gpf)
ENTRY(int80_direct_trap)
ASM_CLAC
pushq $0
SAVE_VOLATILE 0x80
movl $0x80, 4(%rsp)
SAVE_ALL
cmpb $0,untrusted_msi(%rip)
UNLIKELY_START(ne, msi_check)
@@ -253,7 +254,6 @@ int80_slow_path:
* IDT entry with DPL==0.
*/
movl $((0x80 << 3) | X86_XEC_IDT),UREGS_error_code(%rsp)
SAVE_PRESERVED
movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
/* A GPF wouldn't have incremented the instruction pointer. */
subq $2,UREGS_rip(%rsp)
+4 -9
View File
@@ -80,15 +80,10 @@ static void _show_registers(
regs->rbp, regs->rsp, regs->r8);
printk("r9: %016lx r10: %016lx r11: %016lx\n",
regs->r9, regs->r10, regs->r11);
if ( !(regs->entry_vector & TRAP_regs_partial) )
{
printk("r12: %016lx r13: %016lx r14: %016lx\n",
regs->r12, regs->r13, regs->r14);
printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
regs->r15, crs[0], crs[4]);
}
else
printk("cr0: %016lx cr4: %016lx\n", crs[0], crs[4]);
printk("r12: %016lx r13: %016lx r14: %016lx\n",
regs->r12, regs->r13, regs->r14);
printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
regs->r15, crs[0], crs[4]);
printk("cr3: %016lx cr2: %016lx\n", crs[3], crs[2]);
printk("fsb: %016lx gsb: %016lx gss: %016lx\n",
crs[5], crs[6], crs[7]);
-1
View File
@@ -11,7 +11,6 @@
#include <xen/domain_page.h>
#include <asm/x86_emulate.h>
#include <asm/asm_defns.h> /* mark_regs_dirty() */
#include <asm/processor.h> /* current_cpu_info */
#include <asm/xstate.h>
#include <asm/amd.h> /* cpu_has_amd_erratum() */
+4 -4
View File
@@ -1956,10 +1956,10 @@ decode_register(
case 9: p = &regs->r9; break;
case 10: p = &regs->r10; break;
case 11: p = &regs->r11; break;
case 12: mark_regs_dirty(regs); p = &regs->r12; break;
case 13: mark_regs_dirty(regs); p = &regs->r13; break;
case 14: mark_regs_dirty(regs); p = &regs->r14; break;
case 15: mark_regs_dirty(regs); p = &regs->r15; break;
case 12: p = &regs->r12; break;
case 13: p = &regs->r13; break;
case 14: p = &regs->r14; break;
case 15: p = &regs->r15; break;
#endif
default: BUG(); p = NULL; break;
}
-1
View File
@@ -127,7 +127,6 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
unsigned long dummy;
u32 entry_vector = cpu_info->guest_cpu_user_regs.entry_vector;
cpu_info->guest_cpu_user_regs.entry_vector &= ~TRAP_regs_partial;
ASSERT(wqv->esp == 0);
/* Save current VCPU affinity; force wakeup on *this* CPU only. */
+8 -97
View File
@@ -17,15 +17,6 @@
void ret_from_intr(void);
#endif
#ifdef CONFIG_FRAME_POINTER
/* Indicate special exception stack frame by inverting the frame pointer. */
#define SETUP_EXCEPTION_FRAME_POINTER(offs) \
leaq offs(%rsp),%rbp; \
notq %rbp
#else
#define SETUP_EXCEPTION_FRAME_POINTER(offs)
#endif
#ifndef NDEBUG
#define ASSERT_INTERRUPT_STATUS(x, msg) \
pushf; \
@@ -42,31 +33,6 @@ void ret_from_intr(void);
#define ASSERT_INTERRUPTS_DISABLED \
ASSERT_INTERRUPT_STATUS(z, "INTERRUPTS DISABLED")
/*
* This flag is set in an exception frame when registers R12-R15 did not get
* saved.
*/
#define _TRAP_regs_partial 16
#define TRAP_regs_partial (1 << _TRAP_regs_partial)
/*
* This flag gets set in an exception frame when registers R12-R15 possibly
* get modified from their originally saved values and hence need to be
* restored even if the normal call flow would restore register values.
*
* The flag being set implies _TRAP_regs_partial to be unset. Restoring
* R12-R15 thus is
* - required when this flag is set,
* - safe when _TRAP_regs_partial is unset.
*/
#define _TRAP_regs_dirty 17
#define TRAP_regs_dirty (1 << _TRAP_regs_dirty)
#define mark_regs_dirty(r) ({ \
struct cpu_user_regs *r__ = (r); \
ASSERT(!((r__)->entry_vector & TRAP_regs_partial)); \
r__->entry_vector |= TRAP_regs_dirty; \
})
#ifdef __ASSEMBLY__
# define _ASM_EX(p) p-.
#else
@@ -236,7 +202,7 @@ static always_inline void stac(void)
#endif
#ifdef __ASSEMBLY__
.macro SAVE_ALL op
.macro SAVE_ALL op, compat=0
.ifeqs "\op", "CLAC"
ASM_CLAC
.else
@@ -255,40 +221,6 @@ static always_inline void stac(void)
movq %rdx,UREGS_rdx(%rsp)
movq %rcx,UREGS_rcx(%rsp)
movq %rax,UREGS_rax(%rsp)
movq %r8,UREGS_r8(%rsp)
movq %r9,UREGS_r9(%rsp)
movq %r10,UREGS_r10(%rsp)
movq %r11,UREGS_r11(%rsp)
movq %rbx,UREGS_rbx(%rsp)
movq %rbp,UREGS_rbp(%rsp)
SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
movq %r12,UREGS_r12(%rsp)
movq %r13,UREGS_r13(%rsp)
movq %r14,UREGS_r14(%rsp)
movq %r15,UREGS_r15(%rsp)
.endm
/*
* Save all registers not preserved by C code or used in entry/exit code. Mark
* the frame as partial.
*
* @type: exception type
* @compat: R8-R15 don't need saving, and the frame nevertheless is complete
*/
.macro SAVE_VOLATILE type compat=0
.if \compat
movl $\type,UREGS_entry_vector-UREGS_error_code(%rsp)
.else
movl $\type|TRAP_regs_partial,\
UREGS_entry_vector-UREGS_error_code(%rsp)
.endif
addq $-(UREGS_error_code-UREGS_r15),%rsp
cld
movq %rdi,UREGS_rdi(%rsp)
movq %rsi,UREGS_rsi(%rsp)
movq %rdx,UREGS_rdx(%rsp)
movq %rcx,UREGS_rcx(%rsp)
movq %rax,UREGS_rax(%rsp)
.if !\compat
movq %r8,UREGS_r8(%rsp)
movq %r9,UREGS_r9(%rsp)
@@ -297,20 +229,17 @@ static always_inline void stac(void)
.endif
movq %rbx,UREGS_rbx(%rsp)
movq %rbp,UREGS_rbp(%rsp)
SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
.endm
/*
* Complete a frame potentially only partially saved.
*/
.macro SAVE_PRESERVED
btrl $_TRAP_regs_partial,UREGS_entry_vector(%rsp)
jnc 987f
#ifdef CONFIG_FRAME_POINTER
/* Indicate special exception stack frame by inverting the frame pointer. */
leaq UREGS_rbp(%rsp), %rbp
notq %rbp
#endif
.if !\compat
movq %r12,UREGS_r12(%rsp)
movq %r13,UREGS_r13(%rsp)
movq %r14,UREGS_r14(%rsp)
movq %r15,UREGS_r15(%rsp)
987:
.endif
.endm
#define LOAD_ONE_REG(reg, compat) \
@@ -330,7 +259,6 @@ static always_inline void stac(void)
*/
.macro RESTORE_ALL adj=0 compat=0
.if !\compat
testl $TRAP_regs_dirty,UREGS_entry_vector(%rsp)
movq UREGS_r11(%rsp),%r11
movq UREGS_r10(%rsp),%r10
movq UREGS_r9(%rsp),%r9
@@ -347,33 +275,16 @@ static always_inline void stac(void)
LOAD_ONE_REG(si, \compat)
LOAD_ONE_REG(di, \compat)
.if !\compat
jz 987f
movq UREGS_r15(%rsp),%r15
movq UREGS_r14(%rsp),%r14
movq UREGS_r13(%rsp),%r13
movq UREGS_r12(%rsp),%r12
#ifndef NDEBUG
.subsection 1
987: testl $TRAP_regs_partial,UREGS_entry_vector(%rsp)
jnz 987f
cmpq UREGS_r15(%rsp),%r15
jne 789f
cmpq UREGS_r14(%rsp),%r14
jne 789f
cmpq UREGS_r13(%rsp),%r13
jne 789f
cmpq UREGS_r12(%rsp),%r12
je 987f
789: BUG /* Corruption of partial register state. */
.subsection 0
#endif
.else
xor %r15, %r15
xor %r14, %r14
xor %r13, %r13
xor %r12, %r12
.endif
987:
LOAD_ONE_REG(bp, \compat)
LOAD_ONE_REG(bx, \compat)
subq $-(UREGS_error_code-UREGS_r15+\adj), %rsp
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.