From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: "Andrew Cooper" <andrew.cooper3@citrix.com>,
"Wei Liu" <wei.liu2@citrix.com>,
"Roger Pau Monné" <roger.pau@citrix.com>
Subject: [PATCH v2 5/5] x86/pv: Implement the failsafe callback using the general path
Date: Tue, 27 Feb 2018 14:50:36 +0000 [thread overview]
Message-ID: <1519743036-11600-6-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1519743036-11600-1-git-send-email-andrew.cooper3@citrix.com>
Reintroduce TBF_FAILSAFE and update pv_create_exception_frame() to cope with
the additional data segment registers.
load_segments() now fills in trap_bounce, and lets the general return-to-guest
path inject the exception.
Bloat-o-meter reports:
add/remove: 0/0 grow/shrink: 1/1 up/down: 123/-2522 (-2399)
function old new delta
pv_create_exception_frame 1088 1211 +123
context_switch 3565 1043 -2522
which I suspect is largely due to the quantity of code hidden behind
put_user().
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v2:
* Use const uregs.
---
xen/arch/x86/domain.c | 100 +++-------------------------------------
xen/arch/x86/pv/traps.c | 29 ++++++++++--
xen/include/asm-x86/processor.h | 1 +
3 files changed, 32 insertions(+), 98 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 69679a6..7bce7de 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1354,100 +1354,14 @@ static void load_segments(struct vcpu *n)
if ( unlikely(!all_segs_okay) )
{
- struct pv_vcpu *pv = &n->arch.pv_vcpu;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
- unsigned long *rsp =
- (unsigned long *)(((n->arch.flags & TF_kernel_mode)
- ? regs->rsp : pv->kernel_sp) & ~0xf);
- unsigned long cs_and_mask, rflags;
-
- /* Fold upcall mask and architectural IOPL into RFLAGS.IF. */
- rflags = regs->rflags & ~(X86_EFLAGS_IF|X86_EFLAGS_IOPL);
- rflags |= !vcpu_info(n, evtchn_upcall_mask) << 9;
- if ( VM_ASSIST(n->domain, architectural_iopl) )
- rflags |= n->arch.pv_vcpu.iopl;
-
- if ( is_pv_32bit_vcpu(n) )
- {
- unsigned int *esp = ring_1(regs) ?
- (unsigned int *)regs->rsp :
- (unsigned int *)pv->kernel_sp;
- int ret = 0;
-
- /* CS longword also contains full evtchn_upcall_mask. */
- cs_and_mask = (unsigned short)regs->cs |
- ((unsigned int)vcpu_info(n, evtchn_upcall_mask) << 16);
-
- if ( !ring_1(regs) )
- {
- ret = put_user(regs->ss, esp-1);
- ret |= put_user(regs->esp, esp-2);
- esp -= 2;
- }
-
- if ( ret |
- put_user(rflags, esp-1) |
- put_user(cs_and_mask, esp-2) |
- put_user(regs->eip, esp-3) |
- put_user(uregs->gs, esp-4) |
- put_user(uregs->fs, esp-5) |
- put_user(uregs->es, esp-6) |
- put_user(uregs->ds, esp-7) )
- {
- gprintk(XENLOG_ERR,
- "error while creating compat failsafe callback frame\n");
- domain_crash(n->domain);
- }
+ bool disable = n->arch.vgc_flags & VGCF_failsafe_disables_events;
- if ( n->arch.vgc_flags & VGCF_failsafe_disables_events )
- vcpu_info(n, evtchn_upcall_mask) = 1;
-
- regs->entry_vector |= TRAP_syscall;
- regs->eflags &= ~(X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT|
- X86_EFLAGS_IOPL|X86_EFLAGS_TF);
- regs->ss = FLAT_COMPAT_KERNEL_SS;
- regs->esp = (unsigned long)(esp-7);
- regs->cs = FLAT_COMPAT_KERNEL_CS;
- regs->eip = pv->failsafe_callback_eip;
- return;
- }
-
- if ( !(n->arch.flags & TF_kernel_mode) )
- toggle_guest_mode(n);
- else
- regs->cs &= ~3;
-
- /* CS longword also contains full evtchn_upcall_mask. */
- cs_and_mask = (unsigned long)regs->cs |
- ((unsigned long)vcpu_info(n, evtchn_upcall_mask) << 32);
-
- if ( put_user(regs->ss, rsp- 1) |
- put_user(regs->rsp, rsp- 2) |
- put_user(rflags, rsp- 3) |
- put_user(cs_and_mask, rsp- 4) |
- put_user(regs->rip, rsp- 5) |
- put_user(uregs->gs, rsp- 6) |
- put_user(uregs->fs, rsp- 7) |
- put_user(uregs->es, rsp- 8) |
- put_user(uregs->ds, rsp- 9) |
- put_user(regs->r11, rsp-10) |
- put_user(regs->rcx, rsp-11) )
- {
- gprintk(XENLOG_ERR,
- "error while creating failsafe callback frame\n");
- domain_crash(n->domain);
- }
-
- if ( n->arch.vgc_flags & VGCF_failsafe_disables_events )
- vcpu_info(n, evtchn_upcall_mask) = 1;
-
- regs->entry_vector |= TRAP_syscall;
- regs->rflags &= ~(X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF|
- X86_EFLAGS_NT|X86_EFLAGS_IOPL|X86_EFLAGS_TF);
- regs->ss = FLAT_KERNEL_SS;
- regs->rsp = (unsigned long)(rsp-11);
- regs->cs = FLAT_KERNEL_CS;
- regs->rip = pv->failsafe_callback_eip;
+ n->arch.pv_vcpu.trap_bounce = (struct trap_bounce){
+ .flags = (TBF_FAILSAFE | TBF_EXCEPTION |
+ (disable ? TBF_INTERRUPT : 0)),
+ .cs = FLAT_COMPAT_KERNEL_CS, /* Ignored for 64bit guests. */
+ .eip = n->arch.pv_vcpu.failsafe_callback_eip
+ };
}
}
diff --git a/xen/arch/x86/pv/traps.c b/xen/arch/x86/pv/traps.c
index b7d7d2b..8745e44 100644
--- a/xen/arch/x86/pv/traps.c
+++ b/xen/arch/x86/pv/traps.c
@@ -258,6 +258,7 @@ void pv_create_exception_frame(void)
struct vcpu *curr = current;
struct trap_bounce *tb = &curr->arch.pv_vcpu.trap_bounce;
struct cpu_user_regs *regs = guest_cpu_user_regs();
+ const struct cpu_user_regs *uregs = &curr->arch.user_regs;
const bool user_mode_frame = !guest_kernel_mode(curr, regs);
uint8_t *evt_mask = &vcpu_info(curr, evtchn_upcall_mask);
unsigned int flags, bytes, missing;
@@ -279,10 +280,18 @@ void pv_create_exception_frame(void)
if ( is_pv_32bit_vcpu(curr) )
{
- /* { [ERRCODE,] EIP, CS/MASK , EFLAGS, [ESP, SS] } */
- unsigned int frame[6], *ptr = frame, ksp =
+ /* { [DS-GS,] [ERRCODE,] EIP, CS/MASK , EFLAGS, [ESP, SS] } */
+ unsigned int frame[10], *ptr = frame, ksp =
(user_mode_frame ? curr->arch.pv_vcpu.kernel_sp : regs->esp);
+ if ( tb->flags & TBF_FAILSAFE )
+ {
+ *ptr++ = uregs->ds;
+ *ptr++ = uregs->es;
+ *ptr++ = uregs->fs;
+ *ptr++ = uregs->gs;
+ }
+
if ( tb->flags & TBF_EXCEPTION_ERRCODE )
*ptr++ = tb->error_code;
@@ -321,13 +330,15 @@ void pv_create_exception_frame(void)
regs->rflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_RF |
X86_EFLAGS_NT | X86_EFLAGS_TF);
regs->rsp = ksp;
- if ( user_mode_frame )
+ if ( tb->flags & TBF_FAILSAFE )
+ regs->ss = FLAT_COMPAT_KERNEL_SS;
+ else if ( user_mode_frame )
regs->ss = curr->arch.pv_vcpu.kernel_ss;
}
else
{
- /* { RCX, R11, [ERRCODE,] RIP, CS/MASK, RFLAGS, RSP, SS } */
- unsigned long frame[8], *ptr = frame, ksp =
+ /* { RCX, R11, [DS-GS,] [ERRCODE,] RIP, CS/MASK, RFLAGS, RSP, SS } */
+ unsigned long frame[12], *ptr = frame, ksp =
(user_mode_frame ? curr->arch.pv_vcpu.kernel_sp : regs->rsp) & ~0xf;
if ( user_mode_frame )
@@ -336,6 +347,14 @@ void pv_create_exception_frame(void)
*ptr++ = regs->rcx;
*ptr++ = regs->r11;
+ if ( tb->flags & TBF_FAILSAFE )
+ {
+ *ptr++ = uregs->ds;
+ *ptr++ = uregs->es;
+ *ptr++ = uregs->fs;
+ *ptr++ = uregs->gs;
+ }
+
if ( tb->flags & TBF_EXCEPTION_ERRCODE )
*ptr++ = tb->error_code;
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 01bc89f..4fba9a4 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -61,6 +61,7 @@
/* 'trap_bounce' flags values */
#define TBF_EXCEPTION 1
#define TBF_EXCEPTION_ERRCODE 2
+#define TBF_FAILSAFE 4
#define TBF_INTERRUPT 8
/* 'arch_vcpu' flags values */
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
prev parent reply other threads:[~2018-02-27 14:50 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-27 14:50 [PATCH v2 0/5] x86: Lift create_exception_frame() up out of C Andrew Cooper
2018-02-27 14:50 ` [PATCH v2 1/5] x86/entry: Correct comparisons against boolean variables Andrew Cooper
2018-03-02 16:27 ` Jan Beulich
2018-03-02 17:32 ` Wei Liu
2018-02-27 14:50 ` [PATCH v2 2/5] x86/pv: Drop int80_bounce from struct pv_vcpu Andrew Cooper
2018-02-27 14:50 ` [PATCH v2 3/5] x86/pv: Introduce pv_create_exception_frame() Andrew Cooper
2018-03-02 16:44 ` Jan Beulich
2018-02-27 14:50 ` [PATCH v2 4/5] x86/pv: Drop {compat_, }create_bounce_frame() and use the C version instead Andrew Cooper
2018-03-05 9:27 ` Jan Beulich
2018-09-07 14:17 ` Andrew Cooper
2018-09-07 15:49 ` Jan Beulich
2018-02-27 14:50 ` Andrew Cooper [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1519743036-11600-6-git-send-email-andrew.cooper3@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=roger.pau@citrix.com \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).