[PATCH 1/2 gnumach] xen with smp now compiles

Damien Zammit <[email protected]> Thu, 02 Jul 2026 10:30:25 +0000
Newsgroups gmane.os.hurd.bugs
Message-ID <[email protected]>
UNTESTED: Needs gdt and idt fixed for vcpus

(See warning in code compilation)
---
 i386/Makefrag.am        |   6 +++
 i386/Makefrag_x86.am    |   2 -
 i386/i386/ast_check.c   |   5 ++
 i386/i386/i386asm.sym   |  15 +++---
 i386/i386/locore.S      |   5 +-
 i386/i386/mp_desc.c     | 114 +++++++++++++++++++++++++++++++++++++++-
 i386/i386/percpu.c      |  39 +++++++++++---
 i386/i386/percpu.h      |   6 +++
 i386/i386/spl.S         |  10 ++--
 i386/i386/xen.h         |  52 +++++++++++++++++-
 i386/i386at/model_dep.h |   1 +
 i386/xen/xen.c          |  12 +++++
 i386/xen/xen_locore.S   |  29 ++++++++--
 x86_64/Makefrag.am      |   6 +++
 x86_64/locore.S         |   5 +-
 x86_64/spl.S            |  10 ++--
 x86_64/xen_locore.S     |  29 ++++++++--
 17 files changed, 311 insertions(+), 35 deletions(-)

diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index 85333d1e..f54efeee 100644
--- a/i386/Makefrag.am
+++ b/i386/Makefrag.am
@@ -112,6 +112,12 @@ libkernel_a_SOURCES += \
 	i386/i386/pit.c \
 	i386/i386/pit.h
 
+if enable_smp
+libkernel_a_SOURCES += \
+	i386/i386/smp.c \
+	i386/i386/smp.h
+endif
+
 if enable_apic
 libkernel_a_SOURCES += \
 	i386/i386at/ioapic.c
diff --git a/i386/Makefrag_x86.am b/i386/Makefrag_x86.am
index 56bcf2a8..583d47b4 100644
--- a/i386/Makefrag_x86.am
+++ b/i386/Makefrag_x86.am
@@ -61,8 +61,6 @@ libkernel_a_SOURCES += \
 	i386/i386/sched_param.h \
 	i386/i386/seg.h \
 	i386/i386/setjmp.h \
-	i386/i386/smp.c \
-	i386/i386/smp.h \
 	i386/i386/spl.h \
 	i386/i386/strings.c \
 	i386/i386/task.h \
diff --git a/i386/i386/ast_check.c b/i386/i386/ast_check.c
index 8bf69a68..9d6c1fbe 100644
--- a/i386/i386/ast_check.c
+++ b/i386/i386/ast_check.c
@@ -37,6 +37,7 @@
 #include <kern/smp.h>
 #include <machine/cpu_number.h>
 #include <machine/apic.h>
+#include <machine/xen.h>
 
 /*
  * Initialize for remote invocation of ast_check.
@@ -50,7 +51,11 @@ void init_ast_check(const processor_t processor)
  */
 void cause_ast_check(const processor_t processor)
 {
+#ifndef MACH_XEN
     smp_remote_ast(APIC_LOGICAL_ID(processor->slot_num));
+#else
+    hypsmp_remote_ast(processor->slot_num);
+#endif
 }
 
 #endif	/* NCPUS > 1 */
diff --git a/i386/i386/i386asm.sym b/i386/i386/i386asm.sym
index e1f5c6bb..709375d1 100644
--- a/i386/i386/i386asm.sym
+++ b/i386/i386/i386asm.sym
@@ -181,13 +181,16 @@ offset	thread			th	user_timer
 #endif
 
 #ifdef	MACH_XEN
-offset	shared_info		si	vcpu_info[0].evtchn_upcall_mask	CPU_CLI
-offset	shared_info		si	vcpu_info[0].evtchn_upcall_pending	CPU_PENDING
-offset	shared_info		si	vcpu_info[0].evtchn_pending_sel	CPU_PENDING_SEL
-offset	shared_info		si	evtchn_pending	PENDING
-offset	shared_info		si	evtchn_mask	EVTMASK
+expr	sizeof(vcpu_info_t)					VI_SIZE
+
+offset	shared_info		si	vcpu_info[0]		VI_START
+offset	vcpu_info		vi	evtchn_upcall_mask	CPUX_CLI
+offset	vcpu_info		vi	evtchn_upcall_pending	CPUX_PENDING
+offset	vcpu_info		vi	evtchn_pending_sel	CPUX_PENDING_SEL
+offset	shared_info		si	evtchn_pending		PENDING
+offset	shared_info		si	evtchn_mask		EVTMASK
 #ifdef	MACH_PV_PAGETABLES
-offset	shared_info		si	vcpu_info[0].arch.cr2	CR2
+offset	vcpu_info		vi	arch.cr2		CPUX_CR2
 #endif	/* MACH_PV_PAGETABLES */
 #endif	/* MACH_XEN */
 
diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index dc761991..b6b1d739 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -492,7 +492,10 @@ ENTRY(t_page_fault)
 	pushl	$(T_PAGE_FAULT)		/* mark a page fault trap */
 	pusha				/* save the general registers */
 #ifdef	MACH_PV_PAGETABLES
-	movl	%ss:hyp_shared_info+CR2,%eax
+	pushl	%ebx
+	SET_VCPUX_INFO(%ebx, CPUX_CR2)
+	movl	%ss:(%ebx),%eax
+	popl	%ebx
 #else	/* MACH_PV_PAGETABLES */
 	movl	%cr2,%eax		/* get the faulting address */
 #endif	/* MACH_PV_PAGETABLES */
diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
index 1343861c..873256db 100644
--- a/i386/i386/mp_desc.c
+++ b/i386/i386/mp_desc.c
@@ -24,6 +24,7 @@
  * the rights to redistribute these changes.
  */
 
+#include <kern/ast.h>
 #include <kern/assert.h>
 #include <kern/cpu_number.h>
 #include <kern/debug.h>
@@ -45,6 +46,7 @@
 #include <i386at/int_init.h>
 #include <i386/cpu.h>
 #include <i386/smp.h>
+#include <intel/pmap.h>
 
 #include <i386at/model_dep.h>
 #include <machine/ktss.h>
@@ -95,9 +97,11 @@ interrupt_stack_alloc(void)
 }
 
 #if	NCPUS > 1
+#ifndef MACH_XEN
 phys_addr_t apboot_addr;
 extern void *apboot, *apbootend;
 extern volatile ApicLocalUnit* lapic;
+#endif
 
 /*
  * Multiprocessor i386/i486 systems use a separate copy of the
@@ -205,7 +209,11 @@ cpu_control(int cpu, const int *info, unsigned int count)
 void
 interrupt_processor(int cpu)
 {
+#ifndef MACH_XEN
 	smp_pmap_update(APIC_LOGICAL_ID(cpu));
+#else
+	hypsmp_pmap_update(cpu);
+#endif
 }
 
 static void
@@ -225,6 +233,7 @@ paging_enable(void)
 #endif  /* MACH_HYP */
 }
 
+#ifndef MACH_XEN
 static __attribute__((noreturn)) void
 cpu_setup(int cpu)
 {
@@ -341,4 +350,107 @@ start_other_cpus(void)
 	/* Re-enable IOAPIC interrupts as per setup */
 	lapic_enable();
 }
-#endif	/* NCPUS > 1 */
+
+#else	/* !MACH_XEN */
+
+#include <xen/public/vcpu.h>
+#include <xen/evt.h>
+
+void start_other_cpus(void) {
+	int vcpu;
+	int vcpus;
+	int err;
+	struct vcpu_register_vcpu_info info;
+	volatile struct vcpu_info *vcpui;
+
+	for (vcpus = 0; vcpus < NCPUS; vcpus++) {
+		if (hyp_vcpu_is_up(vcpus) < 0)
+			break;
+        }
+	printf("Xen: Detected %d vCPUS\n", vcpus);
+
+	if (vcpus == 1)
+		return;
+
+	for (vcpu = 1; vcpu < vcpus; vcpu++) {
+		machine_slot[vcpu].running = FALSE;
+	}
+
+	for (vcpu = 1; vcpu < vcpus; vcpu++) {
+
+		init_percpu(vcpu);
+
+		err = hyp_vcpu_initialise(vcpu, &percpu_array[vcpu].vcpu_gc);
+		if (err) {
+			printf("Cannot initialise xen vcpu=%d\n", vcpu);
+			continue;
+		}
+
+		vcpui = &hyp_shared_info.vcpu_info[vcpu];
+		info.mfn = kv_to_mfn(vcpui);
+		info.offset = (uint32_t)((uintptr_t)vcpui & ~PAGE_MASK);
+
+		err = hyp_vcpu_register(vcpu, &info);
+		if (err) {
+			printf("Cannot register xen vcpu=%d\n", vcpu);
+			continue;
+		}
+		percpu_array[vcpu].cpu_id = vcpu;
+
+		err = hyp_vcpu_up(vcpu);
+		if (err) {
+			printf("Cannot bring up xen vcpu=%d\n", vcpu);
+			percpu_array[vcpu].cpu_id = 0;
+			continue;
+		}
+
+		/* Register IPI events per vcpu */
+		percpu_array[vcpu].ast_evt = hyp_event_channel_bind_ipi(vcpu);
+		hyp_evt_handler(percpu_array[vcpu].ast_evt, (interrupt_handler_fn)ast_check, 0, SPLHI);
+
+		percpu_array[vcpu].pmap_evt = hyp_event_channel_bind_ipi(vcpu);
+		hyp_evt_handler(percpu_array[vcpu].pmap_evt, (interrupt_handler_fn)pmap_update_interrupt, 0, SPLHI);
+	}
+
+	for (vcpu = 1; vcpu < vcpus; vcpu++) {
+		printf("Waiting for vCPU %d\n", vcpu);
+
+		do {
+			cpu_pause();
+		} while (machine_slot[vcpu].running == FALSE);
+	}
+	printf("Xen vCPU bringup complete\n");
+}
+
+void cpu_ap_main(void) {
+	int vcpu = cpu_number();
+
+	assert (vcpu > 0);
+
+	mp_desc_init(vcpu);
+	printf("vCPU=(%u) mpdesc done\n", vcpu);
+
+#warning Fix xen smp gdt/idt, see percpu.c and mp_desc.c
+#if 0
+	ap_gdt_init(vcpu);
+	printf("vCPU=(%u) gdt done\n", vcpu);
+
+	ap_idt_init(vcpu);
+	printf("vCPU=(%u) idt done\n", vcpu);
+
+	ap_ldt_init(vcpu);
+	printf("vCPU=(%u) ldt done\n", vcpu);
+
+	ap_ktss_init(vcpu);
+	printf("vCPU=(%u) ktss done\n", vcpu);
+#endif
+	/* Initialize machine_slot fields with the cpu data */
+	machine_slot[vcpu].cpu_subtype = CPU_SUBTYPE_AT386;
+	machine_slot[vcpu].cpu_type = machine_slot[0].cpu_type;
+	machine_slot[vcpu].running = TRUE;
+
+	cpu_launch_first_thread(THREAD_NULL);
+}
+
+#endif /* !MACH_XEN */
+#endif /* NCPUS > 1 */
diff --git a/i386/i386/percpu.c b/i386/i386/percpu.c
index c6b728b6..f4c83e6a 100644
--- a/i386/i386/percpu.c
+++ b/i386/i386/percpu.c
@@ -14,20 +14,47 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <i386/smp.h>
+#ifdef APIC
 #include <i386/apic.h>
+#endif
+#include <i386/gdt.h>
+#include <i386/ldt.h>
+#include <i386/smp.h>
 #include <kern/cpu_number.h>
 #include <i386/percpu.h>
+#include <i386at/model_dep.h>
+
+extern void cpu_ap_main(void);
+extern void hyp_callback(void);
+extern void hyp_failsafe_callback(void);
 
 struct percpu percpu_array[NCPUS] = {0};
 
-#ifndef MACH_XEN
 void init_percpu(int cpu)
 {
-    int apic_id = apic_get_current_cpu();
-
     percpu_array[cpu].self = &percpu_array[cpu];
-    percpu_array[cpu].apic_id = apic_id;
+#ifdef APIC
+    percpu_array[cpu].apic_id = apic_get_current_cpu();
+#endif
     percpu_array[cpu].cpu_id = cpu;
-}
+#if NCPUS > 1 && defined(MACH_XEN)
+    percpu_array[cpu].vcpu_gc.user_regs.eip = (unsigned long)cpu_ap_main;
+    percpu_array[cpu].vcpu_gc.flags = VGCF_IN_KERNEL;
+    percpu_array[cpu].vcpu_gc.user_regs.eflags = 0x1000; /* IOPL_RING1 */
+    percpu_array[cpu].vcpu_gc.user_regs.ds = USER_DS;
+    percpu_array[cpu].vcpu_gc.user_regs.es = USER_DS;
+    percpu_array[cpu].vcpu_gc.user_regs.ss = KERNEL_DS;
+    percpu_array[cpu].vcpu_gc.user_regs.cs = KERNEL_CS;
+    percpu_array[cpu].vcpu_gc.user_regs.esp = (unsigned long)int_stack_top[cpu];
+    //XXX gdt_{frames,ents} ?
+    //XXX trap_ctxt (idt)?
+    percpu_array[cpu].vcpu_gc.kernel_ss = KERNEL_DS;
+    percpu_array[cpu].vcpu_gc.kernel_sp = (unsigned long)int_stack_top[cpu];
+#ifdef __x86_64__
+    percpu_array[cpu].vcpu_gc.gs_base_kernel = (unsigned long)percpu_array[cpu].self;
 #endif
+    percpu_array[cpu].vcpu_gc.event_callback_eip = (unsigned long)hyp_callback;
+    percpu_array[cpu].vcpu_gc.failsafe_callback_eip = (unsigned long)hyp_failsafe_callback;
+    percpu_array[cpu].vcpu_gc.ctrlreg[3] = (unsigned long)kernel_page_dir;
+#endif
+}
diff --git a/i386/i386/percpu.h b/i386/i386/percpu.h
index 637d2ca6..52556835 100644
--- a/i386/i386/percpu.h
+++ b/i386/i386/percpu.h
@@ -67,11 +67,17 @@ MACRO_END
 
 #include <kern/processor.h>
 #include <mach/mach_types.h>
+#include <i386/xen.h>
 
 struct percpu {
     struct percpu	*self;
     int			apic_id;
     int			cpu_id;
+#ifdef MACH_XEN
+    struct vcpu_guest_context vcpu_gc;
+    evtchn_port_t	ast_evt;
+    evtchn_port_t	pmap_evt;
+#endif
     struct processor	processor;
     thread_t		active_thread;
     vm_offset_t		active_stack;
diff --git a/i386/i386/spl.S b/i386/i386/spl.S
index 1a831edb..5ae2589e 100644
--- a/i386/i386/spl.S
+++ b/i386/i386/spl.S
@@ -40,11 +40,13 @@
 	notl	%ebx;				\
 	andl	%eax,%ebx;			/* Get unmasked events */ \
 	testl	hyp_shared_info+PENDING, %ebx;	\
-	popl	%ebx;				\
 	jz	9f;				/* Check whether there was some pending */ \
-lock	orl	$1,hyp_shared_info+CPU_PENDING_SEL; /* Yes, activate it */ \
-	movb	$1,hyp_shared_info+CPU_PENDING; \
-9:
+	SET_VCPUX_INFO(%ebx, CPUX_PENDING_SEL);	\
+lock	orl	$1, (%ebx); 			/* Yes, activate it */ \
+	SET_VCPUX_INFO(%ebx, CPUX_PENDING);	\
+	movb	$1, (%ebx);			\
+9:						\
+	popl	%ebx;
 
 ENTRY(spl0)
 	mb;
diff --git a/i386/i386/xen.h b/i386/i386/xen.h
index 2cd81be8..5001fc42 100644
--- a/i386/i386/xen.h
+++ b/i386/i386/xen.h
@@ -351,6 +351,12 @@ static inline evtchn_port_t hyp_event_channel_bind_virq(uint32_t virq, uint32_t
 		panic("can't bind virq %d\n",virq);
 	return op.u.bind_virq.port;
 }
+static inline evtchn_port_t hyp_event_channel_bind_ipi(uint32_t vcpu) {
+	evtchn_op_t op = { .cmd = EVTCHNOP_bind_ipi, .u.bind_ipi = { .vcpu = vcpu }};
+	if (hyp_event_channel_op(kvtolin(&op)))
+		panic("can't bind ipi to vcpu %d\n",vcpu);
+	return op.u.bind_ipi.port;
+}
 
 _hypcall3(int, console_io, int, cmd, int, count, vm_offset_t /* const char * */, buffer);
 
@@ -360,6 +366,14 @@ _hypcall2(long, vm_assist, unsigned int, cmd, unsigned int, type);
 
 _hypcall0(long, iret);
 
+#include <xen/public/vcpu.h>
+_hypcall3(int, vcpu_op, int, cmd, int, vcpu, vm_offset_t /* void* */, arg)
+#define hyp_vcpu_initialise(vcpu, gc) hyp_vcpu_op(VCPUOP_initialise, vcpu, (vm_offset_t)gc)
+#define hyp_vcpu_register(vcpu, info) hyp_vcpu_op(VCPUOP_register_vcpu_info, vcpu, (vm_offset_t)info)
+#define hyp_vcpu_is_up(vcpu) hyp_vcpu_op(VCPUOP_is_up, vcpu, 0)
+#define hyp_vcpu_up(vcpu) hyp_vcpu_op(VCPUOP_up, vcpu, 0)
+#define hyp_vcpu_down(vcpu) hyp_vcpu_op(VCPUOP_down, vcpu, 0)
+
 #include <xen/public/sched.h>
 _hypcall2(long, sched_op, int, cmd, vm_offset_t /* void* */, arg)
 #define hyp_yield() hyp_sched_op(SCHEDOP_yield, 0)
@@ -401,9 +415,43 @@ static inline uint64_t hyp_cpu_clock(void) {
 	return (((uint64_t) hi) << 32) | lo;
 }
 
+void hypsmp_remote_ast(int vcpu);
+void hypsmp_pmap_update(int vcpu);
+
 #else	/* __ASSEMBLER__ */
-/* TODO: SMP */
-#define cli movb $0xff,hyp_shared_info+CPU_CLI
+#include <i386/i386/i386asm.h>
+
+#ifdef __i386__
+/* Don't call this with %eax */
+#define SET_VCPUX_INFO(reg, offset)	\
+	pushl	%eax;			\
+	pushl	%ebx;			\
+	pushl	%edx;			\
+	CPU_NUMBER(%ebx);		\
+	movl	$VI_SIZE, %eax;		\
+	mull	%ebx;			\
+	movl	$(hyp_shared_info+VI_START), reg; \
+	movl	offset(reg, %eax, 1), reg; \
+	popl	%edx;			\
+	popl	%ebx;			\
+	popl	%eax;
+#endif
+#ifdef __x86_64__
+/* Don't call this with %rax */
+#define SET_VCPUX_INFO(reg, offset)	\
+	pushq	%rax;			\
+	pushq	%rbx;			\
+	pushq	%rdx;			\
+	CPU_NUMBER(%ebx);		\
+	movq	$VI_SIZE, %rax;		\
+	mulq	%rbx;			\
+	movq	$(hyp_shared_info+VI_START), reg; \
+	movq	offset(reg, %rax, 1), reg; \
+	popq	%rdx;			\
+	popq	%rbx;			\
+	popq	%rax;
+#endif
+#define cli call hyp_cli
 #define sti call hyp_sti
 #define iretq jmp hyp_iretq
 #endif	/* ASSEMBLER */
diff --git a/i386/i386at/model_dep.h b/i386/i386at/model_dep.h
index 3d5b6645..85a37e47 100644
--- a/i386/i386at/model_dep.h
+++ b/i386/i386at/model_dep.h
@@ -21,6 +21,7 @@
 
 #include <i386/vm_param.h>
 #include <mach/vm_prot.h>
+#include <sys/types.h>
 
 /*
  * Interrupt stack.
diff --git a/i386/xen/xen.c b/i386/xen/xen.c
index 1cc3fcab..d86d80c2 100644
--- a/i386/xen/xen.c
+++ b/i386/xen/xen.c
@@ -20,6 +20,7 @@
 #include <kern/debug.h>
 #include <kern/mach_clock.h>
 
+#include <mach/vm_param.h>
 #include <mach/machine/eflags.h>
 #include <machine/thread.h>
 #include <machine/ipl.h>
@@ -28,6 +29,7 @@
 #include <vm/pmap.h>
 
 #include <xen/xen.h>
+#include <i386/percpu.h>
 
 unsigned long cr3;
 
@@ -69,3 +71,13 @@ void hyp_p2m_init(void) {
 #endif
 	hyp_shared_info.arch.max_pfn = nb_pfns;
 }
+
+void hypsmp_remote_ast(int vcpu)
+{
+	hyp_event_channel_send(percpu_array[vcpu].ast_evt);
+}
+
+void hypsmp_pmap_update(int vcpu)
+{
+	hyp_event_channel_send(percpu_array[vcpu].pmap_evt);
+}
diff --git a/i386/xen/xen_locore.S b/i386/xen/xen_locore.S
index 1468ef80..b642440a 100644
--- a/i386/xen/xen_locore.S
+++ b/i386/xen/xen_locore.S
@@ -56,20 +56,26 @@ ENTRY(hyp_sti)
 	pushl	%ebp
 	movl	%esp, %ebp
 _hyp_sti:
-	movb	$0,hyp_shared_info+CPU_CLI /* Enable interrupts */
+	pushl	%ebx
+	SET_VCPUX_INFO(%ebx, CPUX_CLI)
+	movb	$0,(%ebx)		/* Enable interrupts */
 	cmpl	$0,int_active		/* Check whether we were already checking pending interrupts */
 	jz	0f
+	popl	%ebx
 	popl	%ebp
 	ret				/* Already active, just return */
 0:
 	/* Not active, check pending interrupts by hand */
 	/* no memory barrier needed on x86 */
-	cmpb	$0,hyp_shared_info+CPU_PENDING
+	SET_VCPUX_INFO(%ebx, CPUX_PENDING)
+	cmpb	$0,(%ebx)
 	jne	0f
+	popl	%ebx
 	popl	%ebp
 	ret
 0:
-	movb	$0xff,hyp_shared_info+CPU_CLI
+	popl	%ebx
+	cli
 1:
 	pushl	%eax
 	pushl	%ecx
@@ -86,10 +92,25 @@ _hyp_sti:
 	popl	%ecx
 	popl	%eax
 	decl	int_active		/* stopped handling interrupts */
-	cmpb	$0,hyp_shared_info+CPU_PENDING
+	pushl	%ebx
+	SET_VCPUX_INFO(%ebx, CPUX_PENDING)
+	cmpb	$0,(%ebx)
+	popl	%ebx
 	jne	1b
 	jmp	_hyp_sti
 
+ENTRY(hyp_cli)
+	pushl	%ebp
+	movl	%esp, %ebp
+
+	pushl	%ebx
+	SET_VCPUX_INFO(%ebx, CPUX_CLI)
+	movb	$0xff,(%ebx)
+	popl	%ebx
+
+	popl	%ebp
+	ret
+
 /* Hypervisor failed to reload segments. Dump them.  */
 hyp_failsafe_callback:
 #if 1
diff --git a/x86_64/Makefrag.am b/x86_64/Makefrag.am
index 36b5fa38..bc82cec9 100644
--- a/x86_64/Makefrag.am
+++ b/x86_64/Makefrag.am
@@ -110,6 +110,12 @@ libkernel_a_SOURCES += \
 	i386/i386/pit.c \
 	i386/i386/pit.h
 
+if enable_smp
+libkernel_a_SOURCES += \
+	i386/i386/smp.c \
+	i386/i386/smp.h
+endif
+
 if enable_apic
 libkernel_a_SOURCES += \
 	i386/i386at/ioapic.c
diff --git a/x86_64/locore.S b/x86_64/locore.S
index dd35d2f8..0b2853ca 100644
--- a/x86_64/locore.S
+++ b/x86_64/locore.S
@@ -632,7 +632,10 @@ ENTRY(t_page_fault)
 	pushq	$(T_PAGE_FAULT)		/* mark a page fault trap */
 	pusha				/* save the general registers */
 #ifdef	MACH_XEN
-	movq	%ss:hyp_shared_info+CR2,%rax
+	pushq	%rbx
+	SET_VCPUX_INFO(%rbx, CPUX_CR2)
+	movq	%ss:(%rbx),%rax
+	popq	%rbx
 #else	/* MACH_XEN */
 	movq	%cr2,%rax		/* get the faulting address */
 #endif	/* MACH_XEN */
diff --git a/x86_64/spl.S b/x86_64/spl.S
index 5fdf977c..28c2b971 100644
--- a/x86_64/spl.S
+++ b/x86_64/spl.S
@@ -39,11 +39,13 @@
 	notl	%ebx;				\
 	andl	%eax,%ebx;			/* Get unmasked events */ \
 	testl	hyp_shared_info+PENDING, %ebx;	\
-	popq	%rbx;				\
 	jz	9f;				/* Check whether there was some pending */ \
-lock	orl	$1,hyp_shared_info+CPU_PENDING_SEL; /* Yes, activate it */ \
-	movb	$1,hyp_shared_info+CPU_PENDING; \
-9:
+	SET_VCPUX_INFO(%rbx, CPUX_PENDING_SEL);	\
+lock	orl	$1,(%rbx);			/* Yes, activate it */ \
+	SET_VCPUX_INFO(%rbx, CPUX_PENDING);	\
+	movb	$1,(%rbx);			\
+9:						\
+	popq	%rbx;
 
 ENTRY(spl0)
 	mb;
diff --git a/x86_64/xen_locore.S b/x86_64/xen_locore.S
index 967c8904..2b2a3ff3 100644
--- a/x86_64/xen_locore.S
+++ b/x86_64/xen_locore.S
@@ -58,20 +58,26 @@ ENTRY(hyp_sti)
 	pushq	%rbp
 	movq	%rsp, %rbp
 _hyp_sti:
-	movb	$0,hyp_shared_info+CPU_CLI /* Enable interrupts */
+	pushq	%rdx
+	SET_VCPUX_INFO(%rdx, CPUX_CLI)
+	movb	$0,(%rdx)		/* Enable interrupts */
 	cmpl	$0,int_active		/* Check whether we were already checking pending interrupts */
 	jz	0f
+	popq	%rdx
 	popq	%rbp
 	ret				/* Already active, just return */
 0:
 	/* Not active, check pending interrupts by hand */
 	/* no memory barrier needed on x86 */
-	cmpb	$0,hyp_shared_info+CPU_PENDING
+	SET_VCPUX_INFO(%rdx, CPUX_PENDING)
+	cmpb	$0,(%rdx)
 	jne	0f
+	popq	%rdx
 	popq	%rbp
 	ret
 0:
-	movb	$0xff,hyp_shared_info+CPU_CLI
+	popq	%rdx
+	cli
 1:
 	pushq	%rax
 	pushq	%rcx
@@ -98,10 +104,25 @@ _hyp_sti:
 	popq	%rcx
 	popq	%rax
 	decl	int_active		/* stopped handling interrupts */
-	cmpb	$0,hyp_shared_info+CPU_PENDING
+	pushq	%rdx
+	SET_VCPUX_INFO(%rdx, CPUX_PENDING)
+	cmpb	$0,(%rdx)
+	popq	%rdx
 	jne	1b
 	jmp	_hyp_sti
 
+ENTRY(hyp_cli)
+	pushq	%rbp
+	movq	%rsp, %rbp
+
+	pushq	%rdx
+	SET_VCPUX_INFO(%rdx, CPUX_CLI)
+	movb	$0xff,(%rdx)
+	popq	%rdx
+
+	popq	%rbp
+	ret
+
 /* Hypervisor failed to reload segments. Dump them.  */
 hyp_failsafe_callback:
 ud2
-- 
2.51.0