diff options
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r-- | arch/x86/kernel/entry_64.S | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index ae63e584c340..80d5663db3bc 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1189,6 +1189,7 @@ END(device_not_available) | |||
1189 | /* runs on exception stack */ | 1189 | /* runs on exception stack */ |
1190 | KPROBE_ENTRY(debug) | 1190 | KPROBE_ENTRY(debug) |
1191 | INTR_FRAME | 1191 | INTR_FRAME |
1192 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1192 | pushq $0 | 1193 | pushq $0 |
1193 | CFI_ADJUST_CFA_OFFSET 8 | 1194 | CFI_ADJUST_CFA_OFFSET 8 |
1194 | paranoidentry do_debug, DEBUG_STACK | 1195 | paranoidentry do_debug, DEBUG_STACK |
@@ -1198,6 +1199,7 @@ KPROBE_END(debug) | |||
1198 | /* runs on exception stack */ | 1199 | /* runs on exception stack */ |
1199 | KPROBE_ENTRY(nmi) | 1200 | KPROBE_ENTRY(nmi) |
1200 | INTR_FRAME | 1201 | INTR_FRAME |
1202 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1201 | pushq $-1 | 1203 | pushq $-1 |
1202 | CFI_ADJUST_CFA_OFFSET 8 | 1204 | CFI_ADJUST_CFA_OFFSET 8 |
1203 | paranoidentry do_nmi, 0, 0 | 1205 | paranoidentry do_nmi, 0, 0 |
@@ -1211,6 +1213,7 @@ KPROBE_END(nmi) | |||
1211 | 1213 | ||
1212 | KPROBE_ENTRY(int3) | 1214 | KPROBE_ENTRY(int3) |
1213 | INTR_FRAME | 1215 | INTR_FRAME |
1216 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1214 | pushq $0 | 1217 | pushq $0 |
1215 | CFI_ADJUST_CFA_OFFSET 8 | 1218 | CFI_ADJUST_CFA_OFFSET 8 |
1216 | paranoidentry do_int3, DEBUG_STACK | 1219 | paranoidentry do_int3, DEBUG_STACK |
@@ -1237,6 +1240,7 @@ END(coprocessor_segment_overrun) | |||
1237 | /* runs on exception stack */ | 1240 | /* runs on exception stack */ |
1238 | ENTRY(double_fault) | 1241 | ENTRY(double_fault) |
1239 | XCPT_FRAME | 1242 | XCPT_FRAME |
1243 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1240 | paranoidentry do_double_fault | 1244 | paranoidentry do_double_fault |
1241 | jmp paranoid_exit1 | 1245 | jmp paranoid_exit1 |
1242 | CFI_ENDPROC | 1246 | CFI_ENDPROC |
@@ -1253,6 +1257,7 @@ END(segment_not_present) | |||
1253 | /* runs on exception stack */ | 1257 | /* runs on exception stack */ |
1254 | ENTRY(stack_segment) | 1258 | ENTRY(stack_segment) |
1255 | XCPT_FRAME | 1259 | XCPT_FRAME |
1260 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1256 | paranoidentry do_stack_segment | 1261 | paranoidentry do_stack_segment |
1257 | jmp paranoid_exit1 | 1262 | jmp paranoid_exit1 |
1258 | CFI_ENDPROC | 1263 | CFI_ENDPROC |
@@ -1278,6 +1283,7 @@ END(spurious_interrupt_bug) | |||
1278 | /* runs on exception stack */ | 1283 | /* runs on exception stack */ |
1279 | ENTRY(machine_check) | 1284 | ENTRY(machine_check) |
1280 | INTR_FRAME | 1285 | INTR_FRAME |
1286 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1281 | pushq $0 | 1287 | pushq $0 |
1282 | CFI_ADJUST_CFA_OFFSET 8 | 1288 | CFI_ADJUST_CFA_OFFSET 8 |
1283 | paranoidentry do_machine_check | 1289 | paranoidentry do_machine_check |
@@ -1312,3 +1318,103 @@ KPROBE_ENTRY(ignore_sysret) | |||
1312 | sysret | 1318 | sysret |
1313 | CFI_ENDPROC | 1319 | CFI_ENDPROC |
1314 | ENDPROC(ignore_sysret) | 1320 | ENDPROC(ignore_sysret) |
1321 | |||
1322 | #ifdef CONFIG_XEN | ||
1323 | ENTRY(xen_hypervisor_callback) | ||
1324 | zeroentry xen_do_hypervisor_callback | ||
1325 | END(xen_hypervisor_callback) | ||
1326 | |||
1327 | /* | ||
1328 | # A note on the "critical region" in our callback handler. | ||
1329 | # We want to avoid stacking callback handlers due to events occurring | ||
1330 | # during handling of the last event. To do this, we keep events disabled | ||
1331 | # until we've done all processing. HOWEVER, we must enable events before | ||
1332 | # popping the stack frame (can't be done atomically) and so it would still | ||
1333 | # be possible to get enough handler activations to overflow the stack. | ||
1334 | # Although unlikely, bugs of that kind are hard to track down, so we'd | ||
1335 | # like to avoid the possibility. | ||
1336 | # So, on entry to the handler we detect whether we interrupted an | ||
1337 | # existing activation in its critical region -- if so, we pop the current | ||
1338 | # activation and restart the handler using the previous one. | ||
1339 | */ | ||
1340 | ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) | ||
1341 | CFI_STARTPROC | ||
1342 | /* Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will | ||
1343 | see the correct pointer to the pt_regs */ | ||
1344 | movq %rdi, %rsp # we don't return, adjust the stack frame | ||
1345 | CFI_ENDPROC | ||
1346 | CFI_DEFAULT_STACK | ||
1347 | 11: incl %gs:pda_irqcount | ||
1348 | movq %rsp,%rbp | ||
1349 | CFI_DEF_CFA_REGISTER rbp | ||
1350 | cmovzq %gs:pda_irqstackptr,%rsp | ||
1351 | pushq %rbp # backlink for old unwinder | ||
1352 | call xen_evtchn_do_upcall | ||
1353 | popq %rsp | ||
1354 | CFI_DEF_CFA_REGISTER rsp | ||
1355 | decl %gs:pda_irqcount | ||
1356 | jmp error_exit | ||
1357 | CFI_ENDPROC | ||
1358 | END(do_hypervisor_callback) | ||
1359 | |||
1360 | /* | ||
1361 | # Hypervisor uses this for application faults while it executes. | ||
1362 | # We get here for two reasons: | ||
1363 | # 1. Fault while reloading DS, ES, FS or GS | ||
1364 | # 2. Fault while executing IRET | ||
1365 | # Category 1 we do not need to fix up as Xen has already reloaded all segment | ||
1366 | # registers that could be reloaded and zeroed the others. | ||
1367 | # Category 2 we fix up by killing the current process. We cannot use the | ||
1368 | # normal Linux return path in this case because if we use the IRET hypercall | ||
1369 | # to pop the stack frame we end up in an infinite loop of failsafe callbacks. | ||
1370 | # We distinguish between categories by comparing each saved segment register | ||
1371 | # with its current contents: any discrepancy means we in category 1. | ||
1372 | */ | ||
1373 | ENTRY(xen_failsafe_callback) | ||
1374 | framesz = (RIP-0x30) /* workaround buggy gas */ | ||
1375 | _frame framesz | ||
1376 | CFI_REL_OFFSET rcx, 0 | ||
1377 | CFI_REL_OFFSET r11, 8 | ||
1378 | movw %ds,%cx | ||
1379 | cmpw %cx,0x10(%rsp) | ||
1380 | CFI_REMEMBER_STATE | ||
1381 | jne 1f | ||
1382 | movw %es,%cx | ||
1383 | cmpw %cx,0x18(%rsp) | ||
1384 | jne 1f | ||
1385 | movw %fs,%cx | ||
1386 | cmpw %cx,0x20(%rsp) | ||
1387 | jne 1f | ||
1388 | movw %gs,%cx | ||
1389 | cmpw %cx,0x28(%rsp) | ||
1390 | jne 1f | ||
1391 | /* All segments match their saved values => Category 2 (Bad IRET). */ | ||
1392 | movq (%rsp),%rcx | ||
1393 | CFI_RESTORE rcx | ||
1394 | movq 8(%rsp),%r11 | ||
1395 | CFI_RESTORE r11 | ||
1396 | addq $0x30,%rsp | ||
1397 | CFI_ADJUST_CFA_OFFSET -0x30 | ||
1398 | pushq $0 | ||
1399 | CFI_ADJUST_CFA_OFFSET 8 | ||
1400 | pushq %r11 | ||
1401 | CFI_ADJUST_CFA_OFFSET 8 | ||
1402 | pushq %rcx | ||
1403 | CFI_ADJUST_CFA_OFFSET 8 | ||
1404 | jmp general_protection | ||
1405 | CFI_RESTORE_STATE | ||
1406 | 1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */ | ||
1407 | movq (%rsp),%rcx | ||
1408 | CFI_RESTORE rcx | ||
1409 | movq 8(%rsp),%r11 | ||
1410 | CFI_RESTORE r11 | ||
1411 | addq $0x30,%rsp | ||
1412 | CFI_ADJUST_CFA_OFFSET -0x30 | ||
1413 | pushq $0 | ||
1414 | CFI_ADJUST_CFA_OFFSET 8 | ||
1415 | SAVE_ALL | ||
1416 | jmp error_exit | ||
1417 | CFI_ENDPROC | ||
1418 | END(xen_failsafe_callback) | ||
1419 | |||
1420 | #endif /* CONFIG_XEN */ | ||