@@ -13,6 +13,7 @@ typedef void (*idtentry_t)(struct pt_regs *regs);
#include <uapi/asm/kvm_para.h>
void __init pvm_early_setup(void);
+void __init pvm_setup_early_traps(void);
void __init pvm_install_sysvec(unsigned int sysvec, idtentry_t handler);
bool __init pvm_kernel_layout_relocate(void);
@@ -70,6 +71,10 @@ static inline void pvm_early_setup(void)
{
}
+static inline void pvm_setup_early_traps(void)
+{
+}
+
static inline void pvm_install_sysvec(unsigned int sysvec, idtentry_t handler)
{
}
@@ -633,6 +633,27 @@ SYM_CODE_START_NOALIGN(vc_no_ghcb)
SYM_CODE_END(vc_no_ghcb)
#endif
+#ifdef CONFIG_PVM_GUEST
+ .align 256
+SYM_CODE_START_NOALIGN(pvm_early_kernel_event_entry)
+ UNWIND_HINT_ENTRY
+ ENDBR
+
+ incl early_recursion_flag(%rip)
+
+ /* set %rcx, %r11 per PVM event handling specification */
+ movq 6*8(%rsp), %rcx
+ movq 7*8(%rsp), %r11
+
+ PUSH_AND_CLEAR_REGS
+ movq %rsp, %rdi /* %rdi -> pt_regs */
+ call pvm_early_event
+
+ decl early_recursion_flag(%rip)
+ jmp pvm_restore_regs_and_return_to_kernel
+SYM_CODE_END(pvm_early_kernel_event_entry)
+#endif
+
#define SYM_DATA_START_PAGE_ALIGNED(name) \
SYM_START(name, SYM_L_GLOBAL, .balign PAGE_SIZE)
@@ -17,6 +17,7 @@
#include <asm/cpu_entry_area.h>
#include <asm/desc.h>
#include <asm/pvm_para.h>
+#include <asm/setup.h>
#include <asm/traps.h>
DEFINE_PER_CPU_PAGE_ALIGNED(struct pvm_vcpu_struct, pvm_vcpu_struct);
@@ -24,6 +25,38 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct pvm_vcpu_struct, pvm_vcpu_struct);
unsigned long pvm_range_start __initdata;
unsigned long pvm_range_end __initdata;
+static bool early_traps_setup __initdata;
+
+void __init pvm_early_event(struct pt_regs *regs)
+{
+ int vector = regs->orig_ax >> 32;
+
+ if (!early_traps_setup) {
+ do_early_exception(regs, vector);
+ return;
+ }
+
+ switch (vector) {
+ case X86_TRAP_DB:
+ exc_debug(regs);
+ return;
+ case X86_TRAP_BP:
+ exc_int3(regs);
+ return;
+ case X86_TRAP_PF:
+ exc_page_fault(regs, regs->orig_ax);
+ return;
+ default:
+ do_early_exception(regs, vector);
+ return;
+ }
+}
+
+void __init pvm_setup_early_traps(void)
+{
+ early_traps_setup = true;
+}
+
static noinstr void pvm_bad_event(struct pt_regs *regs, unsigned long vector,
unsigned long error_code)
{