@@ -1397,6 +1397,85 @@ static void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask)
1397
1397
ctxt -> interruptibility = mask ;
1398
1398
}
1399
1399
1400
+ static inline void
1401
+ setup_syscalls_segments (struct x86_emulate_ctxt * ctxt ,
1402
+ struct kvm_segment * cs , struct kvm_segment * ss )
1403
+ {
1404
+ memset (cs , 0 , sizeof (struct kvm_segment ));
1405
+ kvm_x86_ops -> get_segment (ctxt -> vcpu , cs , VCPU_SREG_CS );
1406
+ memset (ss , 0 , sizeof (struct kvm_segment ));
1407
+
1408
+ cs -> l = 0 ; /* will be adjusted later */
1409
+ cs -> base = 0 ; /* flat segment */
1410
+ cs -> g = 1 ; /* 4kb granularity */
1411
+ cs -> limit = 0xffffffff ; /* 4GB limit */
1412
+ cs -> type = 0x0b ; /* Read, Execute, Accessed */
1413
+ cs -> s = 1 ;
1414
+ cs -> dpl = 0 ; /* will be adjusted later */
1415
+ cs -> present = 1 ;
1416
+ cs -> db = 1 ;
1417
+
1418
+ ss -> unusable = 0 ;
1419
+ ss -> base = 0 ; /* flat segment */
1420
+ ss -> limit = 0xffffffff ; /* 4GB limit */
1421
+ ss -> g = 1 ; /* 4kb granularity */
1422
+ ss -> s = 1 ;
1423
+ ss -> type = 0x03 ; /* Read/Write, Accessed */
1424
+ ss -> db = 1 ; /* 32bit stack segment */
1425
+ ss -> dpl = 0 ;
1426
+ ss -> present = 1 ;
1427
+ }
1428
+
1429
+ static int
1430
+ emulate_syscall (struct x86_emulate_ctxt * ctxt )
1431
+ {
1432
+ struct decode_cache * c = & ctxt -> decode ;
1433
+ struct kvm_segment cs , ss ;
1434
+ u64 msr_data ;
1435
+
1436
+ /* syscall is not available in real mode */
1437
+ if (c -> lock_prefix || ctxt -> mode == X86EMUL_MODE_REAL
1438
+ || !(ctxt -> vcpu -> arch .cr0 & X86_CR0_PE ))
1439
+ return -1 ;
1440
+
1441
+ setup_syscalls_segments (ctxt , & cs , & ss );
1442
+
1443
+ kvm_x86_ops -> get_msr (ctxt -> vcpu , MSR_STAR , & msr_data );
1444
+ msr_data >>= 32 ;
1445
+ cs .selector = (u16 )(msr_data & 0xfffc );
1446
+ ss .selector = (u16 )(msr_data + 8 );
1447
+
1448
+ if (is_long_mode (ctxt -> vcpu )) {
1449
+ cs .db = 0 ;
1450
+ cs .l = 1 ;
1451
+ }
1452
+ kvm_x86_ops -> set_segment (ctxt -> vcpu , & cs , VCPU_SREG_CS );
1453
+ kvm_x86_ops -> set_segment (ctxt -> vcpu , & ss , VCPU_SREG_SS );
1454
+
1455
+ c -> regs [VCPU_REGS_RCX ] = c -> eip ;
1456
+ if (is_long_mode (ctxt -> vcpu )) {
1457
+ #ifdef CONFIG_X86_64
1458
+ c -> regs [VCPU_REGS_R11 ] = ctxt -> eflags & ~EFLG_RF ;
1459
+
1460
+ kvm_x86_ops -> get_msr (ctxt -> vcpu ,
1461
+ ctxt -> mode == X86EMUL_MODE_PROT64 ?
1462
+ MSR_LSTAR : MSR_CSTAR , & msr_data );
1463
+ c -> eip = msr_data ;
1464
+
1465
+ kvm_x86_ops -> get_msr (ctxt -> vcpu , MSR_SYSCALL_MASK , & msr_data );
1466
+ ctxt -> eflags &= ~(msr_data | EFLG_RF );
1467
+ #endif
1468
+ } else {
1469
+ /* legacy mode */
1470
+ kvm_x86_ops -> get_msr (ctxt -> vcpu , MSR_STAR , & msr_data );
1471
+ c -> eip = (u32 )msr_data ;
1472
+
1473
+ ctxt -> eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF );
1474
+ }
1475
+
1476
+ return 0 ;
1477
+ }
1478
+
1400
1479
int
1401
1480
x86_emulate_insn (struct x86_emulate_ctxt * ctxt , struct x86_emulate_ops * ops )
1402
1481
{
@@ -1993,7 +2072,10 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1993
2072
}
1994
2073
break ;
1995
2074
case 0x05 : /* syscall */
1996
- goto cannot_emulate ;
2075
+ if (emulate_syscall (ctxt ) == -1 )
2076
+ goto cannot_emulate ;
2077
+ else
2078
+ goto writeback ;
1997
2079
break ;
1998
2080
case 0x06 :
1999
2081
emulate_clts (ctxt -> vcpu );
0 commit comments