Skip to content

Commit aa13497

Browse files
Lai Jiangshanbysui
authored andcommitted
PVM: remove synthetic RETS instruction
and remove MSR_PVM_RETS_RIP Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com>
1 parent 126eb43 commit aa13497

7 files changed

Lines changed: 76 additions & 43 deletions

File tree

arch/x86/entry/entry_64_pvm.S

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "calling.h"
99

10+
#define REDZONE_SIZE 16
11+
1012
/* Construct struct pt_regs on stack */
1113
.macro PUSH_IRET_FRAME_FROM_PVCS user:req
1214
movq %rsp, %r11
@@ -24,7 +26,7 @@
2426
* event from supervisor mode. This is for the int3 handler
2527
* to emulate a call instruction.
2628
*/
27-
subq $16, %rsp
29+
subq $REDZONE_SIZE, %rsp
2830

2931
/* TODO: check stack overflow */
3032

@@ -174,11 +176,67 @@ SYM_CODE_START(pvm_kernel_event_entry)
174176
ENDBR
175177

176178
PUSH_IRET_FRAME_FROM_PVCS user=0
179+
180+
// if RIP < .L_pvm_supervisor_iret_irq_enabled_start ==> skip fixup
181+
leaq .L_pvm_supervisor_iret_irq_enabled_start(%rip), %rcx
182+
cmpq RIP-RIP(%rsp), %rcx
183+
ja .L_pvm_supervisor_iret_irq_fixed
184+
185+
// if RIP >= .L_pvm_supervisor_iret_irq_enabled_end ==> skip fixup
186+
leaq .L_pvm_supervisor_iret_irq_enabled_end(%rip), %rcx
187+
cmpq RIP-RIP(%rsp), %rcx
188+
jbe .L_pvm_supervisor_iret_irq_fixed
189+
190+
// fixup to Previous IRET Frame
191+
// Previous IRET Frame
192+
// RAX
193+
// RCX
194+
// R11
195+
// HW_ring3 IRET Frame <-- origin rsp
196+
// padding for alignment (8 bytes)
197+
// RED_ZONE (16 bytes)
198+
// Current IRET Frame
199+
movq RSP-RIP(%rsp), %rcx
200+
movq (16+40)(%rcx), %rax
201+
movq ( 8+40)(%rcx), %r11
202+
movq %r11, PER_CPU_VAR(pvm_vcpu_struct + PVCS_rcx)
203+
movq ( 0+40)(%rcx), %r11
204+
leaq (24+40)(%rcx), %rsp
205+
.L_pvm_supervisor_iret_irq_fixed:
206+
movq PER_CPU_VAR(pvm_vcpu_struct + PVCS_rcx), %rcx
207+
177208
PUSH_REGS_AND_HANDLE_EVENT handler=pvm_event
178-
POP_REGS_AND_LOAD_IRET_FRAME_INTO_PVCS
179-
SYM_INNER_LABEL(pvm_rets_rip, SYM_L_GLOBAL)
180-
ANNOTATE_NOENDBR
209+
210+
.L_pvm_supervisor_restore_regs_and_return:
211+
POP_REGS
212+
movq %rax, (%rsp)
213+
pushq %rcx
214+
pushq %r11
215+
mov %ss, %rax
216+
pushq %rax /* current hw SS for supervisor_iret */
217+
pushq 8*7(%rsp) /* RSP */
218+
pushq 8*7(%rsp) /* RFLAGS */
219+
mov %cs, %rax
220+
pushq %rax /* current hw CS for supervisor_iret */
221+
pushq 8*7(%rsp) /* RIP */
222+
testl $X86_EFLAGS_IF, EFLAGS-RIP(%rsp)
223+
jz .L_pvm_supervisor_iret
224+
orq $X86_EFLAGS_IF, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_flags)
225+
.L_pvm_supervisor_iret_irq_enabled_start:
226+
btq $PVM_EVENT_FLAGS_IP_BIT, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_flags)
227+
jc .L_pvm_supervisor_iret_irq_pending
228+
.L_pvm_supervisor_iret:
229+
movq 8*7(%rsp), %rax
230+
iretq
231+
.L_pvm_supervisor_iret_irq_pending:
232+
/* handle pending IRQ */
233+
movq $PVM_HC_IRQ_WIN, %rax
181234
syscall
235+
// normally don't reach here, but it can only happend when there is actually no IRQ pending
236+
movq 8*5(%rsp), %r11
237+
movq 8*6(%rsp), %rcx
238+
jmp .L_pvm_supervisor_iret
239+
.L_pvm_supervisor_iret_irq_enabled_end:
182240
SYM_CODE_END(pvm_kernel_event_entry)
183241

184242
.pushsection .head.text, "ax"
@@ -189,8 +247,7 @@ SYM_CODE_START_NOALIGN(pvm_early_kernel_event_entry)
189247
incl early_recursion_flag(%rip)
190248
PUSH_IRET_FRAME_FROM_PVCS user=0
191249
PUSH_REGS_AND_HANDLE_EVENT handler=pvm_early_event
192-
POP_REGS_AND_LOAD_IRET_FRAME_INTO_PVCS
193250
decl early_recursion_flag(%rip)
194-
jmp pvm_rets_rip
251+
jmp .L_pvm_supervisor_restore_regs_and_return
195252
SYM_CODE_END(pvm_early_kernel_event_entry)
196253
.popsection

arch/x86/include/asm/pvm_para.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ void entry_SYSCALL_64_pvm(void);
9191
void pvm_user_event_entry(void);
9292
void pvm_hypercall(void);
9393
void pvm_retu_rip(void);
94-
void pvm_rets_rip(void);
9594
void pvm_save_fl(void);
9695
void pvm_irq_disable(void);
9796
void pvm_irq_enable(void);

arch/x86/include/uapi/asm/pvm_para.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
// #define MSR_PVM_SUPERVISOR_RSP 0x4b564df3 // deprecated, FIXME: reordering when sending v2
3535
#define MSR_PVM_EVENT_ENTRY 0x4b564df4
3636
#define MSR_PVM_RETU_RIP 0x4b564df5
37-
#define MSR_PVM_RETS_RIP 0x4b564df6
37+
// #define MSR_PVM_RETS_RIP 0x4b564df6
3838

3939
#define PVM_HC_SPECIAL_MAX_NR (256)
4040
#define PVM_HC_SPECIAL_BASE (0x17088200)

arch/x86/kernel/pvm.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,6 @@ void __init pvm_early_setup(void)
496496

497497
wrmsrl(MSR_PVM_VCPU_STRUCT, __pa(this_cpu_ptr(&pvm_vcpu_struct)));
498498
wrmsrl(MSR_PVM_EVENT_ENTRY, (unsigned long)(void *)pvm_early_kernel_event_entry - 512);
499-
wrmsrl(MSR_PVM_RETS_RIP, (unsigned long)(void *)pvm_rets_rip);
500499

501500
pvm_early_patch();
502501
}
@@ -509,7 +508,6 @@ void pvm_setup_event_handling(void)
509508
wrmsrl(MSR_PVM_VCPU_STRUCT, xpa);
510509
wrmsrl(MSR_PVM_EVENT_ENTRY, (unsigned long)(void *)pvm_user_event_entry);
511510
wrmsrl(MSR_PVM_RETU_RIP, (unsigned long)(void *)pvm_retu_rip);
512-
wrmsrl(MSR_PVM_RETS_RIP, (unsigned long)(void *)pvm_rets_rip);
513511

514512
/*
515513
* PVM spec requires the hypervisor-maintained

arch/x86/kvm/pvm/pvm.c

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,9 +1084,6 @@ static int pvm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
10841084
case MSR_PVM_RETU_RIP:
10851085
msr_info->data = pvm->msr_retu_rip_plus2 - 2;
10861086
break;
1087-
case MSR_PVM_RETS_RIP:
1088-
msr_info->data = pvm->msr_rets_rip_plus2 - 2;
1089-
break;
10901087
case MSR_PVM_LINEAR_ADDRESS_RANGE:
10911088
msr_info->data = pvm->msr_linear_address_range;
10921089
break;
@@ -1234,9 +1231,6 @@ static int pvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
12341231
case MSR_PVM_RETU_RIP:
12351232
pvm->msr_retu_rip_plus2 = msr_info->data + 2;
12361233
break;
1237-
case MSR_PVM_RETS_RIP:
1238-
pvm->msr_rets_rip_plus2 = msr_info->data + 2;
1239-
break;
12401234
case MSR_PVM_LINEAR_ADDRESS_RANGE:
12411235
if (!pvm_check_and_set_msr_linear_address_range(pvm, msr_info->data))
12421236
return 1;
@@ -1573,7 +1567,7 @@ static int __do_pvm_event(struct kvm_vcpu *vcpu, bool user, int vector,
15731567
* the hypervisor to meet the requirement stipulated above in
15741568
* case it is on the path to ERETU.
15751569
*
1576-
* When forced back to handle_synthetic_instruction_return(),
1570+
* When forced back to handle_synthetic_instruction_return_user(),
15771571
* SWITCH_FLAGS_IRQ_WIN will be cleared in kvm_set_rflags() or
15781572
* unhandled NMI/MCE will be reinjected.
15791573
*/
@@ -1776,16 +1770,15 @@ static void pvm_setup_mce(struct kvm_vcpu *vcpu)
17761770
{
17771771
}
17781772

1779-
static int handle_synthetic_instruction_return(struct kvm_vcpu *vcpu, bool user)
1773+
static int handle_synthetic_instruction_return_user(struct kvm_vcpu *vcpu)
17801774
{
17811775
struct vcpu_pvm *pvm = to_pvm(vcpu);
17821776
struct pvm_vcpu_struct *pvcs;
17831777
unsigned long rflags;
17841778
u32 pending_async_exceptions;
17851779

17861780
/* switch to user mode before rsp changed. */
1787-
if (user)
1788-
switch_to_umod(vcpu);
1781+
switch_to_umod(vcpu);
17891782

17901783
pvcs = pvm_get_vcpu_struct(pvm);
17911784
if (!pvcs) {
@@ -1794,21 +1787,16 @@ static int handle_synthetic_instruction_return(struct kvm_vcpu *vcpu, bool user)
17941787
}
17951788

17961789
pending_async_exceptions = pvcs->event_vector;
1797-
if (user)
1798-
pvcs->event_vector = PVM_PVCS_EVENT_VECTOR_STD;
1799-
else
1800-
pvcs->event_vector = 0;
1790+
pvcs->event_vector = PVM_PVCS_EVENT_VECTOR_STD; // Clear other bits
18011791

18021792
kvm_rip_write(vcpu, pvcs->rip);
18031793
kvm_rcx_write(vcpu, pvcs->rcx);
18041794
kvm_r11_write(vcpu, pvcs->r11);
18051795
rflags = pvcs->eflags;
18061796

1807-
if (user) {
1808-
pvm->hw_cs = pvcs->user_cs | USER_RPL;
1809-
pvm->hw_ss = pvcs->user_ss | USER_RPL;
1810-
pvm_write_guest_gs_base(pvm, pvcs->user_gsbase);
1811-
}
1797+
pvm->hw_cs = pvcs->user_cs | USER_RPL;
1798+
pvm->hw_ss = pvcs->user_ss | USER_RPL;
1799+
pvm_write_guest_gs_base(pvm, pvcs->user_gsbase);
18121800

18131801
pvm_put_vcpu_struct(pvm, true);
18141802

@@ -1819,9 +1807,9 @@ static int handle_synthetic_instruction_return(struct kvm_vcpu *vcpu, bool user)
18191807
kvm_set_rflags(vcpu, rflags);
18201808

18211809
if (pending_async_exceptions & PVM_PVCS_EVENT_VECTOR_MCE)
1822-
__do_pvm_event(vcpu, user, MC_VECTOR, false, 0);
1810+
do_pvm_event(vcpu, MC_VECTOR, false, 0);
18231811
if (pending_async_exceptions & PVM_PVCS_EVENT_VECTOR_NMI)
1824-
__do_pvm_event(vcpu, user, NMI_VECTOR, false, 0);
1812+
do_pvm_event(vcpu, NMI_VECTOR, false, 0);
18251813

18261814
return 1;
18271815
}
@@ -2094,9 +2082,7 @@ static int handle_exit_syscall(struct kvm_vcpu *vcpu)
20942082
return __do_pvm_event(vcpu, true, PVM_SYSCALL_VECTOR, false, 0);
20952083

20962084
if (rip == pvm->msr_retu_rip_plus2)
2097-
return handle_synthetic_instruction_return(vcpu, true);
2098-
if (rip == pvm->msr_rets_rip_plus2)
2099-
return handle_synthetic_instruction_return(vcpu, false);
2085+
return handle_synthetic_instruction_return_user(vcpu);
21002086

21012087
a0 = kvm_rbx_read(vcpu);
21022088
a1 = kvm_r10_read(vcpu);
@@ -2398,8 +2384,6 @@ static u32 pvm_get_syscall_exit_reason(struct kvm_vcpu *vcpu)
23982384
if (is_smod(pvm)) {
23992385
if (rip == pvm->msr_retu_rip_plus2)
24002386
return PVM_EXIT_REASONS_ERETU;
2401-
else if (rip == pvm->msr_rets_rip_plus2)
2402-
return PVM_EXIT_REASONS_ERETS;
24032387
else
24042388
return PVM_EXIT_REASONS_HYPERCALL;
24052389
}
@@ -2853,7 +2837,6 @@ static void pvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
28532837
pvm->msr_vcpu_struct = 0;
28542838
pvm->msr_event_entry = 0;
28552839
pvm->msr_retu_rip_plus2 = 0;
2856-
pvm->msr_rets_rip_plus2 = 0;
28572840
pvm_set_default_msr_linear_address_range(pvm);
28582841
}
28592842

arch/x86/kvm/pvm/pvm.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
#define PVM_EXIT_REASONS_SYSCALL (1UL << PVM_EXIT_REASONS_SHIFT)
3030
#define PVM_EXIT_REASONS_HYPERCALL (2UL << PVM_EXIT_REASONS_SHIFT)
3131
#define PVM_EXIT_REASONS_ERETU (3UL << PVM_EXIT_REASONS_SHIFT)
32-
#define PVM_EXIT_REASONS_ERETS (4UL << PVM_EXIT_REASONS_SHIFT)
33-
#define PVM_EXIT_REASONS_INTERRUPT (5UL << PVM_EXIT_REASONS_SHIFT)
34-
#define PVM_EXIT_REASONS_INT80 (6UL << PVM_EXIT_REASONS_SHIFT)
32+
#define PVM_EXIT_REASONS_INTERRUPT (4UL << PVM_EXIT_REASONS_SHIFT)
33+
#define PVM_EXIT_REASONS_INT80 (5UL << PVM_EXIT_REASONS_SHIFT)
3534

3635
#define PVM_EXIT_REASONS \
3736
{ DE_VECTOR, "DE excp" }, \
@@ -55,7 +54,6 @@
5554
{ PVM_EXIT_REASONS_SYSCALL, "SYSCALL" }, \
5655
{ PVM_EXIT_REASONS_HYPERCALL, "HYPERCALL" }, \
5756
{ PVM_EXIT_REASONS_ERETU, "ERETU" }, \
58-
{ PVM_EXIT_REASONS_ERETS, "ERETS" }, \
5957
{ PVM_EXIT_REASONS_INTERRUPT, "INTERRUPT" }, \
6058
{ PVM_EXIT_REASONS_INT80, "INT80" }, \
6159
{ PVM_FAILED_VMENTRY_VECTOR, "FAILED_VMENTRY" }
@@ -136,7 +134,6 @@ struct vcpu_pvm {
136134
unsigned long msr_vcpu_struct;
137135
unsigned long msr_event_entry;
138136
unsigned long msr_retu_rip_plus2;
139-
unsigned long msr_rets_rip_plus2;
140137
unsigned long msr_linear_address_range;
141138

142139
u64 l4_range_start;

arch/x86/kvm/x86.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,6 @@ static const u32 emulated_msrs_all[] = {
15301530
MSR_PVM_VCPU_STRUCT,
15311531
MSR_PVM_EVENT_ENTRY,
15321532
MSR_PVM_RETU_RIP,
1533-
MSR_PVM_RETS_RIP,
15341533

15351534
MSR_IA32_TSC_ADJUST,
15361535
MSR_IA32_TSC_DEADLINE,

0 commit comments

Comments
 (0)