Commit 59dbb9d8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xsa465+xsa466-6.13-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen fixes from Juergen Gross:
 "Fix xen netfront crash (XSA-465) and avoid using the hypercall page
  that doesn't do speculation mitigations (XSA-466)"

* tag 'xsa465+xsa466-6.13-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  x86/xen: remove hypercall page
  x86/xen: use new hypercall functions instead of hypercall page
  x86/xen: add central hypercall functions
  x86/xen: don't do PV iret hypercall through hypercall page
  x86/static-call: provide a way to do very early static-call updates
  objtool/x86: allow syscall instruction
  x86: make get_cpu_vendor() accessible from Xen code
  xen/netfront: fix crash when removing device
parents f44d154d 7fa0da53
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -230,6 +230,8 @@ static inline unsigned long long l1tf_pfn_limit(void)
	return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT);
}

void init_cpu_devs(void);
void get_cpu_vendor(struct cpuinfo_x86 *c);
extern void early_cpu_init(void);
extern void identify_secondary_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
+15 −0
Original line number Diff line number Diff line
@@ -65,4 +65,19 @@

extern bool __static_call_fixup(void *tramp, u8 op, void *dest);

extern void __static_call_update_early(void *tramp, void *func);

#define static_call_update_early(name, _func)				\
({									\
	typeof(&STATIC_CALL_TRAMP(name)) __F = (_func);			\
	if (static_call_initialized) {					\
		__static_call_update(&STATIC_CALL_KEY(name),		\
				     STATIC_CALL_TRAMP_ADDR(name), __F);\
	} else {							\
		WRITE_ONCE(STATIC_CALL_KEY(name).func, _func);		\
		__static_call_update_early(STATIC_CALL_TRAMP_ADDR(name),\
					   __F);			\
	}								\
})

#endif /* _ASM_STATIC_CALL_H */
+3 −3
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
#include <asm/special_insns.h>

#ifdef CONFIG_X86_32
static inline void iret_to_self(void)
static __always_inline void iret_to_self(void)
{
	asm volatile (
		"pushfl\n\t"
@@ -19,7 +19,7 @@ static inline void iret_to_self(void)
		: ASM_CALL_CONSTRAINT : : "memory");
}
#else
static inline void iret_to_self(void)
static __always_inline void iret_to_self(void)
{
	unsigned int tmp;

@@ -55,7 +55,7 @@ static inline void iret_to_self(void)
 * Like all of Linux's memory ordering operations, this is a
 * compiler barrier as well.
 */
static inline void sync_core(void)
static __always_inline void sync_core(void)
{
	/*
	 * The SERIALIZE instruction is the most straightforward way to
+22 −14
Original line number Diff line number Diff line
@@ -39,9 +39,11 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/pgtable.h>
#include <linux/instrumentation.h>

#include <trace/events/xen.h>

#include <asm/alternative.h>
#include <asm/page.h>
#include <asm/smap.h>
#include <asm/nospec-branch.h>
@@ -86,11 +88,20 @@ struct xen_dm_op_buf;
 * there aren't more than 5 arguments...)
 */

extern struct { char _entry[32]; } hypercall_page[];
void xen_hypercall_func(void);
DECLARE_STATIC_CALL(xen_hypercall, xen_hypercall_func);

#define __HYPERCALL		"call hypercall_page+%c[offset]"
#define __HYPERCALL_ENTRY(x)						\
	[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
#ifdef MODULE
#define __ADDRESSABLE_xen_hypercall
#else
#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall)
#endif

#define __HYPERCALL					\
	__ADDRESSABLE_xen_hypercall			\
	"call __SCT__xen_hypercall"

#define __HYPERCALL_ENTRY(x)	"a" (x)

#ifdef CONFIG_X86_32
#define __HYPERCALL_RETREG	"eax"
@@ -148,7 +159,7 @@ extern struct { char _entry[32]; } hypercall_page[];
	__HYPERCALL_0ARG();						\
	asm volatile (__HYPERCALL					\
		      : __HYPERCALL_0PARAM				\
		      : __HYPERCALL_ENTRY(name)				\
		      : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name)	\
		      : __HYPERCALL_CLOBBER0);				\
	(type)__res;							\
})
@@ -159,7 +170,7 @@ extern struct { char _entry[32]; } hypercall_page[];
	__HYPERCALL_1ARG(a1);						\
	asm volatile (__HYPERCALL					\
		      : __HYPERCALL_1PARAM				\
		      : __HYPERCALL_ENTRY(name)				\
		      : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name)	\
		      : __HYPERCALL_CLOBBER1);				\
	(type)__res;							\
})
@@ -170,7 +181,7 @@ extern struct { char _entry[32]; } hypercall_page[];
	__HYPERCALL_2ARG(a1, a2);					\
	asm volatile (__HYPERCALL					\
		      : __HYPERCALL_2PARAM				\
		      : __HYPERCALL_ENTRY(name)				\
		      : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name)	\
		      : __HYPERCALL_CLOBBER2);				\
	(type)__res;							\
})
@@ -181,7 +192,7 @@ extern struct { char _entry[32]; } hypercall_page[];
	__HYPERCALL_3ARG(a1, a2, a3);					\
	asm volatile (__HYPERCALL					\
		      : __HYPERCALL_3PARAM				\
		      : __HYPERCALL_ENTRY(name)				\
		      : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name)	\
		      : __HYPERCALL_CLOBBER3);				\
	(type)__res;							\
})
@@ -192,7 +203,7 @@ extern struct { char _entry[32]; } hypercall_page[];
	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
	asm volatile (__HYPERCALL					\
		      : __HYPERCALL_4PARAM				\
		      : __HYPERCALL_ENTRY(name)				\
		      : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name)	\
		      : __HYPERCALL_CLOBBER4);				\
	(type)__res;							\
})
@@ -206,12 +217,9 @@ xen_single_call(unsigned int call,
	__HYPERCALL_DECLS;
	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);

	if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
		return -EINVAL;

	asm volatile(CALL_NOSPEC
	asm volatile(__HYPERCALL
		     : __HYPERCALL_5PARAM
		     : [thunk_target] "a" (&hypercall_page[call])
		     : __HYPERCALL_ENTRY(call)
		     : __HYPERCALL_CLOBBER5);

	return (long)__res;
+0 −5
Original line number Diff line number Diff line
@@ -142,11 +142,6 @@ static bool skip_addr(void *dest)
	if (dest >= (void *)relocate_kernel &&
	    dest < (void*)relocate_kernel + KEXEC_CONTROL_CODE_MAX_SIZE)
		return true;
#endif
#ifdef CONFIG_XEN
	if (dest >= (void *)hypercall_page &&
	    dest < (void*)hypercall_page + PAGE_SIZE)
		return true;
#endif
	return false;
}
Loading