diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-07-08 18:06:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-16 04:59:52 -0400 |
commit | 3d75e1b8ef1567348ceba93d4666a1c7c2333583 (patch) | |
tree | f01b3e3b229757b0ee9e8d06b3a8e99d8de8128d /arch/x86/kernel/entry_64.S | |
parent | 7d087b68d6ddb2398fb7f6e45990b7248de640ef (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.S | 98 |
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 |
1314 | ENDPROC(ignore_sysret) | 1314 | ENDPROC(ignore_sysret) |
1315 | |||
1316 | #ifdef CONFIG_XEN | ||
1317 | ENTRY(xen_hypervisor_callback) | ||
1318 | zeroentry xen_do_hypervisor_callback | ||
1319 | END(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 | */ | ||
1334 | ENTRY(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 | ||
1341 | 11: 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 | ||
1352 | END(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 | */ | ||
1367 | ENTRY(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 | ||
1397 | 1: /* 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 | ||
1410 | END(xen_failsafe_callback) | ||
1411 | |||
1412 | #endif /* CONFIG_XEN */ | ||