1111.macro PUSH_IRET_FRAME_FROM_PVCS user: req
1212 .if \user == 1
1313 movl PER_CPU_VAR(pvm_vcpu_struct + PVCS_user_ss), %ecx
14- andq $0xff , %rcx
14+ andl $0xFFFF , %ecx
1515 pushq %rcx /* pt_regs->ss */
1616 .else
1717 pushq $__KERNEL_DS
2323
2424 .if \user == 1
2525 movl PER_CPU_VAR(pvm_vcpu_struct + PVCS_user_cs), %ecx
26- andq $0xff , %rcx
26+ andl $0xFFFF , %ecx
2727 pushq %rcx /* pt_regs->cs */
2828 .else
2929 pushq $__KERNEL_CS
3636 movq PER_CPU_VAR(pvm_vcpu_struct + PVCS_r11), %r11
3737.endm
3838
39- .macro pvm_enable_events
40- orq $PVM_EVENT_FLAGS_EF, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_flags)
41- btq $PVM_EVENT_FLAGS_EP_BIT, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_flags)
42- jnc .L_no_event_pending_\@
43- pushq %rax
44- movq $PVM_HC_EVENT_WIN, %rax
45- call pvm_hypercall
46- popq %rax
47- .L_no_event_pending_\@:
39+ .macro PUSH_REGS_AND_HANDLE_EVENT handler: req
40+ /* Invalidate orig_ax so that syscall_get_nr() works correctly */
41+ pushq $-1
42+ PUSH_AND_CLEAR_REGS
43+
44+ movw PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_errcode), %dx
45+ xorl %esi , %esi
46+ // get all async exceptions and put PVCS with non-contended xchg
47+ xchgw %si , PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_vector)
48+ movq %rsp , %rdi /* %rdi -> pt_regs */
49+ call \handler
4850.endm
4951
50- .macro pvm_disable_events
51- btrq $PVM_EVENT_FLAGS_EF_BIT, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_flags)
52+ .macro POP_REGS_AND_LOAD_IRET_FRAME_INTO_PVCS
53+ POP_REGS
54+
55+ // get PVCS before access to it
56+ btsw $PVM_PVCS_EVENT_VECTOR_STD_BIT, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_vector)
57+
58+ // Copy %rcx, %r11 to the PVM CPU structure
59+ movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rcx)
60+ movq %r11 , PER_CPU_VAR(pvm_vcpu_struct + PVCS_r11)
61+
62+ // Copy the IRET frame to the PVM CPU structure
63+ // PVCS_user_cs/ss are ignored for ERETS, load them anyway
64+ movq 1*8 (%rsp ), %rcx /* RIP */
65+ movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rip)
66+ movq 2*8 (%rsp ), %rcx /* CS */
67+ movw %cx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_user_cs)
68+ movq 3*8 (%rsp ), %rcx /* RFLAGS */
69+ movl %ecx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_eflags)
70+ movq 4*8 (%rsp ), %rcx /* RSP */
71+ movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rsp)
72+ movq 5*8 (%rsp ), %rcx /* SS */
73+ movw %cx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_user_ss)
5274.endm
5375
5476.code64
@@ -60,8 +82,14 @@ SYM_CODE_START(entry_SYSCALL_64_pvm)
6082
6183 PUSH_IRET_FRAME_FROM_PVCS user =1
6284
63- pvm_enable_events
85+ btrw $PVM_PVCS_EVENT_VECTOR_STD_BIT, PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_vector)
86+ cmpw $0 , PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_vector)
87+ jz entry_SYSCALL_64_after_hwframe
6488
89+ .L_async_exception:
90+ PUSH_REGS_AND_HANDLE_EVENT handler = pvm_event
91+ POP_REGS
92+ addq $8 , %rsp
6593 jmp entry_SYSCALL_64_after_hwframe
6694SYM_CODE_END(entry_SYSCALL_64_pvm)
6795
@@ -97,7 +125,7 @@ SYM_FUNC_START(pvm_irq_enable)
97125 RET
98126.L_maybe_interrupt_pending:
99127 /* handle pending IRQ */
100- movq $PVM_HC_EVENT_WIN , %rax
128+ movq $PVM_HC_IRQ_WIN , %rax
101129 jmp pvm_hypercall
102130SYM_FUNC_END(pvm_irq_enable)
103131.popsection
@@ -112,35 +140,10 @@ SYM_CODE_START(pvm_user_event_entry)
112140 ENDBR
113141
114142 PUSH_IRET_FRAME_FROM_PVCS user =1
115- /* pt_regs->orig_ax: errcode and vector */
116- pushq PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_errcode)
117-
118- pvm_enable_events
119-
120- PUSH_AND_CLEAR_REGS
121- movq %rsp , %rdi /* %rdi -> pt_regs */
122- call pvm_event
143+ PUSH_REGS_AND_HANDLE_EVENT handler = pvm_event
123144
124145SYM_INNER_LABEL(pvm_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
125- POP_REGS
126-
127- pvm_disable_events
128-
129- /* Copy %rcx, %r11 to the PVM CPU structure. */
130- movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rcx)
131- movq %r11 , PER_CPU_VAR(pvm_vcpu_struct + PVCS_r11)
132-
133- /* Copy the IRET frame to the PVM CPU structure. */
134- movq 1*8 (%rsp ), %rcx /* RIP */
135- movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rip)
136- movq 2*8 (%rsp ), %rcx /* CS */
137- movw %cx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_user_cs)
138- movq 3*8 (%rsp ), %rcx /* RFLAGS */
139- movl %ecx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_eflags)
140- movq 4*8 (%rsp ), %rcx /* RSP */
141- movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rsp)
142- movq 5*8 (%rsp ), %rcx /* SS */
143- movw %cx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_user_ss)
146+ POP_REGS_AND_LOAD_IRET_FRAME_INTO_PVCS
144147
145148 /*
146149 * We are on the trampoline stack. All regs are live.
@@ -172,34 +175,26 @@ SYM_CODE_START(pvm_kernel_event_entry)
172175 /* TODO: check stack overflow */
173176
174177 PUSH_IRET_FRAME_FROM_PVCS user =0
175- /* pt_regs->orig_ax: errcode and vector */
176- pushq PER_CPU_VAR(pvm_vcpu_struct + PVCS_event_errcode)
177-
178- pvm_enable_events
179-
180- PUSH_AND_CLEAR_REGS
181- movq %rsp , %rdi /* %rdi -> pt_regs */
182- call pvm_event
183-
184- SYM_INNER_LABEL(pvm_restore_regs_and_return_to_kernel, SYM_L_GLOBAL)
185- POP_REGS
186-
187- pvm_disable_events
188-
189- /* Copy %rcx, %r11 to the PVM CPU structure. */
190- movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rcx)
191- movq %r11 , PER_CPU_VAR(pvm_vcpu_struct + PVCS_r11)
192-
193- /* Copy the IRET frame to the PVM CPU structure. */
194- movq 1*8 (%rsp ), %rcx /* RIP */
195- movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rip)
196- movq 3*8 (%rsp ), %rcx /* RFLAGS */
197- movl %ecx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_eflags)
198- movq 4*8 (%rsp ), %rcx /* RSP */
199- movq %rcx , PER_CPU_VAR(pvm_vcpu_struct + PVCS_rsp)
178+ PUSH_REGS_AND_HANDLE_EVENT handler = pvm_event
179+ POP_REGS_AND_LOAD_IRET_FRAME_INTO_PVCS
200180
201- addq $6*8 , %rsp
181+ addq $( 6*8 + 16 ) , %rsp
202182SYM_INNER_LABEL(pvm_rets_rip, SYM_L_GLOBAL)
203183 ANNOTATE_NOENDBR
204184 syscall
205185SYM_CODE_END(pvm_kernel_event_entry)
186+
187+ .pushsection .head.text, "ax"
188+ SYM_CODE_START_NOALIGN(pvm_early_kernel_event_entry)
189+ UNWIND_HINT_ENTRY
190+ ENDBR
191+
192+ incl early_recursion_flag(%rip )
193+ PUSH_IRET_FRAME_FROM_PVCS user =0
194+ PUSH_REGS_AND_HANDLE_EVENT handler = pvm_early_event
195+ POP_REGS_AND_LOAD_IRET_FRAME_INTO_PVCS
196+ decl early_recursion_flag(%rip )
197+ addq $6*8 , %rsp
198+ jmp pvm_rets_rip
199+ SYM_CODE_END(pvm_early_kernel_event_entry)
200+ .popsection
0 commit comments