aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/entry_64.S
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-07-08 18:06:49 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-16 04:59:52 -0400
commit3d75e1b8ef1567348ceba93d4666a1c7c2333583 (patch)
treef01b3e3b229757b0ee9e8d06b3a8e99d8de8128d /arch/x86/kernel/entry_64.S
parent7d087b68d6ddb2398fb7f6e45990b7248de640ef (diff)
xen64: add hypervisor callbacks for events, etc
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Cc: Stephen Tweedie <sct@redhat.com> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r--arch/x86/kernel/entry_64.S98
1 files changed, 98 insertions, 0 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index ae63e584c340..7cc2de796146 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1312,3 +1312,101 @@ KPROBE_ENTRY(ignore_sysret)
1312 sysret 1312 sysret
1313 CFI_ENDPROC 1313 CFI_ENDPROC
1314ENDPROC(ignore_sysret) 1314ENDPROC(ignore_sysret)
1315
1316#ifdef CONFIG_XEN
1317ENTRY(xen_hypervisor_callback)
1318 zeroentry xen_do_hypervisor_callback
1319END(xen_hypervisor_callback)
1320
1321/*
1322# A note on the "critical region" in our callback handler.
1323# We want to avoid stacking callback handlers due to events occurring
1324# during handling of the last event. To do this, we keep events disabled
1325# until we've done all processing. HOWEVER, we must enable events before
1326# popping the stack frame (can't be done atomically) and so it would still
1327# be possible to get enough handler activations to overflow the stack.
1328# Although unlikely, bugs of that kind are hard to track down, so we'd
1329# like to avoid the possibility.
1330# So, on entry to the handler we detect whether we interrupted an
1331# existing activation in its critical region -- if so, we pop the current
1332# activation and restart the handler using the previous one.
1333*/
1334ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs)
1335 CFI_STARTPROC
1336/* Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
1337 see the correct pointer to the pt_regs */
1338 movq %rdi, %rsp # we don't return, adjust the stack frame
1339 CFI_ENDPROC
1340 CFI_DEFAULT_STACK
134111: incl %gs:pda_irqcount
1342 movq %rsp,%rbp
1343 CFI_DEF_CFA_REGISTER rbp
1344 cmovzq %gs:pda_irqstackptr,%rsp
1345 pushq %rbp # backlink for old unwinder
1346 call xen_evtchn_do_upcall
1347 popq %rsp
1348 CFI_DEF_CFA_REGISTER rsp
1349 decl %gs:pda_irqcount
1350 jmp error_exit
1351 CFI_ENDPROC
1352END(do_hypervisor_callback)
1353
1354/*
1355# Hypervisor uses this for application faults while it executes.
1356# We get here for two reasons:
1357# 1. Fault while reloading DS, ES, FS or GS
1358# 2. Fault while executing IRET
1359# Category 1 we do not need to fix up as Xen has already reloaded all segment
1360# registers that could be reloaded and zeroed the others.
1361# Category 2 we fix up by killing the current process. We cannot use the
1362# normal Linux return path in this case because if we use the IRET hypercall
1363# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
1364# We distinguish between categories by comparing each saved segment register
1365# with its current contents: any discrepancy means we in category 1.
1366*/
1367ENTRY(xen_failsafe_callback)
1368#if 1
1369 ud2a
1370#else
1371 _frame (RIP-0x30)
1372 CFI_REL_OFFSET rcx, 0
1373 CFI_REL_OFFSET r11, 8
1374 movw %ds,%cx
1375 cmpw %cx,0x10(%rsp)
1376 CFI_REMEMBER_STATE
1377 jne 1f
1378 movw %es,%cx
1379 cmpw %cx,0x18(%rsp)
1380 jne 1f
1381 movw %fs,%cx
1382 cmpw %cx,0x20(%rsp)
1383 jne 1f
1384 movw %gs,%cx
1385 cmpw %cx,0x28(%rsp)
1386 jne 1f
1387 /* All segments match their saved values => Category 2 (Bad IRET). */
1388 movq (%rsp),%rcx
1389 CFI_RESTORE rcx
1390 movq 8(%rsp),%r11
1391 CFI_RESTORE r11
1392 addq $0x30,%rsp
1393 CFI_ADJUST_CFA_OFFSET -0x30
1394 movq $11,%rdi /* SIGSEGV */
1395 jmp do_exit
1396 CFI_RESTORE_STATE
13971: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
1398 movq (%rsp),%rcx
1399 CFI_RESTORE rcx
1400 movq 8(%rsp),%r11
1401 CFI_RESTORE r11
1402 addq $0x30,%rsp
1403 CFI_ADJUST_CFA_OFFSET -0x30
1404 pushq $0
1405 CFI_ADJUST_CFA_OFFSET 8
1406 SAVE_ALL
1407 jmp error_exit
1408 CFI_ENDPROC
1409#endif
1410END(xen_failsafe_callback)
1411
1412#endif /* CONFIG_XEN */