* RFC, untested: handing of MSR immediates and MSRs on Xen
@ 2024-10-23 21:31 H. Peter Anvin
2024-10-23 21:34 ` H. Peter Anvin
2024-10-23 21:52 ` H. Peter Anvin
0 siblings, 2 replies; 5+ messages in thread
From: H. Peter Anvin @ 2024-10-23 21:31 UTC (permalink / raw)
To: Xin Li, Xin Li, Andrew Cooper; +Cc: x86, LKML, Peter Zijlstra
So the coming of WRMSRNS immediate and RDMSR immediate forms is now
official in the latest edition (Oct 2024) of the Intel ISE document, see:
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
I have been thinking about how to (a) leverage these instructions to the
best effect and (b) get rid of the code overhead associated with Xen
paravirtualization of a handful of MSRs. As it turns out, the vast
majority of MSRs under Xen are simply passed through anyway; a handful
(perf related) are handled differently, and a small number are ignored.
The immediate form of these instructions are primarily motivated by
performance, not code size: by having the MSR number in an immediate, it
is available *much* earlier in the pipeline, which allows the hardware
much more leeway about how a particular MSR is handled.
Furthermore, we want to continue to minimize the overhead caused by the
remaining users of paravirtualization. The only PV platform left that
intercepts MSRs is Xen.
So, as per previous discussions what we want to do is:
- Have Xen handled by the normal alternatives patching;
- Use an assembly wrapper around the Xen-specific code;
- Allow Xen to invoke the standard error handler by adding a new
exception intercept type: EX_TYPE_INDIRECT. This exception type
takes a register (i.e. _ASM_EXTABLE_TYPE_REG) and then looks up
the exception handler at the address pointed to by that register.
This lets the Xen assembly wrapper deal with error by:
/* let CF be set on error here (any flag condition works) */
jc .L_error
ret
.L_error:
pop %rdx /* Drop return address */
sub $5,%rdx /* Rewind to the beginning of CALL instruction */
1: ud2 /* Any unconditionally trapping instruction */
_ASM_EXTABLE_TYPE_REG(1b, 1b /* unused */, EX_TYPE_INDIRECT, %rdx)
Rather than trying to explain the whole mechanism, I'm including a
crude-and-totally-untested concept implementation for comments and
hopefully, eventually, productization.
Note: I haven't added tracepoint handling yet. *Ideally* tracepoints
would be patched over the main callsite instead of using a separate
static_key() -- which also messes up register allocation due to the
subsequent call. This is a general problem with tracepoints which
perhaps is better handled separately.
-hpa
-hpa
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: RFC, untested: handing of MSR immediates and MSRs on Xen
2024-10-23 21:31 RFC, untested: handing of MSR immediates and MSRs on Xen H. Peter Anvin
@ 2024-10-23 21:34 ` H. Peter Anvin
2024-10-23 22:08 ` Uros Bizjak
2024-10-23 21:52 ` H. Peter Anvin
1 sibling, 1 reply; 5+ messages in thread
From: H. Peter Anvin @ 2024-10-23 21:34 UTC (permalink / raw)
To: Xin Li, Xin Li, Andrew Cooper; +Cc: x86, LKML, Peter Zijlstra
[-- Attachment #1: Type: text/plain, Size: 52 bytes --]
And I of course forgot the include the actual code.
[-- Attachment #2: wrmsrns.c --]
[-- Type: text/x-csrc, Size: 6678 bytes --]
typedef void (*xen_msr_action_t)(void);
#define xen_msr_native ((xen_msr_action_t)NULL)
#define xen_msr_ignore ((xen_msr_action_t)(1UL))
#ifdef CONFIG_XEN
/*** This should go into a Xen-specific header file ***/
/*
* The actual calling convention for the asm_xen_ function is:
* Input:
* %rax - value (full 64-bit value, do not read from %edx)
* %ecx - MSR number
* Output:
* %edx - optionally clobbered
* all other registers preserved
* On error, invoke the trap handler at the stack pointer using
* indirect trapping.
*/
void asm_xen_wrmsrns_general(void);
void asm_xen_wrmsrns_perf(void);
static __must_inline xen_msr_action_t xen_wrmsrns_action(uint32_t msr)
{
if (!__builtin_constant_p(msr))
return asm_xen_wrmsrns_general;
switch (msr) {
case 0x1234:
case 0x5678:
return asm_xen_wrmsrns_perf;
case 0x78:
case 0x89:
return xen_msr_ignore;
default:
return xen_msr_native;
}
}
#else
static __must_inline xen_msr_action_t xen_msr_action(uint32_t msr)
{
return xen_msr_native;
}
#endif
#define EX_WRMSR(from,to) \
_ASM_EXTABLE_TYPE(from, to, EX_TYPE_WRMSR, 0)
#define EX_WRMSR_SAFE(from,to) \
_ASM_EXTABLE_TYPE_REG(from, to, EX_TYPE_WRMSR_SAFE, %[reg])
static __must_inline void wrmsrns_variable(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr);
uint32_t hi = val >> 32;
if (xen_what == xen_msr_native) {
asm_inline volatile(
"1:\n"
ALTERNATIVE("ds wrmsr",
"wrmsrns",
X86_FEATURE_WRMSRNS)
"2:\n"
EX_WRMSR(1b,2b)
: : "a" (val), "d" (hi), "c" (msr),
: "memory");
} else {
asm_inline volatile(
"1:\n"
ALTERNATIVE_2("ds wrmsr",
"wrmsrns",
X86_FEATURE_WRMSRNS,
"call %P[xen]",
X86_FEATURE_XENPV)
"2:\n"
EX_WRMSR(1b,2b)
: [val] "a" (val), "d" (hi), ASM_CALL_CONSTRAINT
: "c" (msr), [xen] "i" (xen_what)
: "memory");
}
}
static __must_inline int wrmsrns_variable_safe(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr);
uint32_t hi = val >> 32;
int err = 0;
if (xen_what == xen_msr_native) {
asm_inline volatile(
"1:\n"
ALTERNATIVE("ds wrmsr; xor %[err],%[err]",
"wrmsrns; xor %[err],%[err]",
X86_FEATURE_WRMSRNS)
"2:\n"
EX_WRMSR_SAFE(1b,2b)
: [err] "=r" (err)
: [val] "a" (val), "d" (hi), [msr] "c" (msr),
: "memory");
} else {
asm_inline volatile(
"1:\n"
ALTERNATIVE_2("ds wrmsr; xor %[err],%[err]"
"wrmsrns; xor %[err],%[err]"
X86_FEATURE_WRMSRNS,
"call %P[xen]",
X86_FEATURE_XENPV)
"2:\n"
EX_WRMSR_SAFE(1b,2b)
: [err] "=r" (err), "+d" (hi), ASM_CALL_CONSTRAINT
: [val] "a" (val), [msr] "c" (msr), [xen] "i" (xen_what)
: "memory");
}
return err;
}
#define WRMSRNS_IMM " .insn VEX.128.F3.M7.W0 0xf6 /0, %[val], %[msr] {:u32}\n"
static __must_inline void wrmsrns_constant(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr, safe);
if (xen_what == xen_msr_native) {
asm_inline volatile(
"1:\n"
ALTERNATIVE_2("mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"1: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM)
"3:\n"
EX_WRMSR(1b,3b) /* For WRMSRNS immediate */
EX_WRMSR(2b,3b) /* For WRMSRNS and WRMSR */
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx");
} else if (xen_what == xen_msr_ignore) {
asm_inline volatile(
"1:\n"
ALTERNATIVE_3("mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"1: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM,
"", X86_FEATURE_XENPV)
"3:\n"
EX_WRMSR(1b,3b) /* For WRMSRNS immediate */
EX_WRMSR(2b,3b) /* For WRMSRNS and WRMSR */
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx");
} else {
asm_inline volatile(
ALTERNATIVE_2("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM);
"3:\n"
EX_WRMSR(1b,3b) /* For Xen and WRMSRNS immediate */
EX_WRMSR(2b,3b) /* For WRMSRNS and WRMSR */
: ASM_CALL_CONSTRAINT
: [val] "a" (val), "c" (msr), [msr] "i" (msr),
[xen] "i" (xen_what)
: "memory", "edx");
}
return err;
}
static __must_inline int wrmsrns_constant_safe(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr, safe);
int err = 0;
if (xen_what == xen_msr_native) {
asm_inline volatile(
"1:\n"
ALTERNATIVE_2("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM)
"3:\n"
EX_WRMSR_SAFE(1b,3b) /* For WRMSRNS immediate */
EX_WRMSR_SAFE(2b,3b) /* For WRMSRNS and WRMSR */
: "+r" (err)
: [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx");
} else if (xen_what == xen_msr_ignore) {
asm_inline volatile(
"1:\n"
ALTERNATIVE_3("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM,
"", X86_FEATURE_XENPV)
"3:\n"
EX_WRMSR_SAFE(1b,3b) /* For WRMSRNS immediate */
EX_WRMSR_SAFE(2b,3b) /* For WRMSRNS and WRMSR */
: "+r" (err)
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx");
} else {
asm_inline volatile(
ALTERNATIVE_3("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM,
"call %P[xen]", X86_FEATURE_XENPV)
"3:\n"
EX_WRMSR_SAFE(1b,3b) /* For Xen and WRMSRNS immediate */
EX_WRMSR_SAFE(2b,3b) /* For WRMSRNS and WRMSR */
: "+r" (err), ASM_CALL_CONSTRAINT
: [val] "a" (val), "c" (msr), [msr] "i" (msr),
[xen] "i" (xen_what)
: "memory", "edx");
}
return err;
}
static inline void wrmsrns(uint32_t msr, uint64_t val)
{
if (__builtin_constant_p(msr))
wrmsrns_constant(msr, val);
else
wrmsrns_variable(msr, val);
}
static inline int wrmsrns_safe(uint32_t msr, uint64_t val)
{
if (__builtin_constant_p(msr))
return wrmsrns_constant_safe(msr, val);
else
return wrmsrns_variable_safe(msr, val);
}
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: RFC, untested: handing of MSR immediates and MSRs on Xen
2024-10-23 21:31 RFC, untested: handing of MSR immediates and MSRs on Xen H. Peter Anvin
2024-10-23 21:34 ` H. Peter Anvin
@ 2024-10-23 21:52 ` H. Peter Anvin
1 sibling, 0 replies; 5+ messages in thread
From: H. Peter Anvin @ 2024-10-23 21:52 UTC (permalink / raw)
To: Xin Li, Xin Li, Andrew Cooper; +Cc: x86, LKML, Peter Zijlstra
On 10/23/24 14:31, H. Peter Anvin wrote:
>
> Note: I haven't added tracepoint handling yet. *Ideally* tracepoints
> would be patched over the main callsite instead of using a separate
> static_key() -- which also messes up register allocation due to the
> subsequent call. This is a general problem with tracepoints which
> perhaps is better handled separately.
>
So I have never quite wrapped my head around how heavyweight tracepoints
actually are. I do know that static_key() is definitely not a perfect
optimization barrier[*].
The case of MSR tracepoints in particular concerns me, because having
one knob for all MSRs is an *incredibly* wide net to cast, and doesn't
distinguish in any way between performance-sensitive and
non-performance-sensitive MSRs.
I do wonder if tracepoint sites could be implemented using traps (or
perhaps better, software interrupts) especially in critical flows, or if
that would increase the cost of the tracing too much.
-hpa
[*] One thing we may want to consider in general is if we should
increase the bias for __builtin_expect() by passing
-fbuiltin-expect-probability to gcc, or use
__builtin_expect_with_probability().
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: RFC, untested: handing of MSR immediates and MSRs on Xen
2024-10-23 21:34 ` H. Peter Anvin
@ 2024-10-23 22:08 ` Uros Bizjak
2024-10-23 23:05 ` H. Peter Anvin
0 siblings, 1 reply; 5+ messages in thread
From: Uros Bizjak @ 2024-10-23 22:08 UTC (permalink / raw)
To: H. Peter Anvin, Xin Li, Xin Li, Andrew Cooper; +Cc: x86, LKML, Peter Zijlstra
On 23. 10. 24 23:34, H. Peter Anvin wrote:
> And I of course forgot the include the actual code.
> ALTERNATIVE_2("ds wrmsr",
> "wrmsrns",
> X86_FEATURE_WRMSRNS,
> "call %P[xen]",
> X86_FEATURE_XENPV)
Please use %c asm operand modifier instead of %P. Please see comment in
arch/x86/include/asm/alternative.h for the reason:
--q--
* Use the %c operand modifier which is the generic way to print a bare
* constant expression with all syntax-specific punctuation omitted. %P
* is the x86-specific variant which can handle constants too, for
* historical reasons, but it should be used primarily for PIC
* references: i.e., if used for a function, it would add the PLT
* suffix.
--/q--
Uros.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: RFC, untested: handing of MSR immediates and MSRs on Xen
2024-10-23 22:08 ` Uros Bizjak
@ 2024-10-23 23:05 ` H. Peter Anvin
0 siblings, 0 replies; 5+ messages in thread
From: H. Peter Anvin @ 2024-10-23 23:05 UTC (permalink / raw)
To: Uros Bizjak, Xin Li, Xin Li, Andrew Cooper; +Cc: x86, LKML, Peter Zijlstra
[-- Attachment #1: Type: text/plain, Size: 328 bytes --]
On 10/23/24 15:08, Uros Bizjak wrote:
>
> Please use %c asm operand modifier instead of %P. Please see comment in
> arch/x86/include/asm/alternative.h for the reason:
>
Here is an updated version which uses asm goto for the safe versions and
changes the type to a boolean.
I also fixed a couple of syntax problems.
-hpa
[-- Attachment #2: wrmsrns2.c --]
[-- Type: text/x-csrc, Size: 7250 bytes --]
typedef void (*xen_msr_action_t)(void);
#define xen_msr_native ((xen_msr_action_t)NULL)
#define xen_msr_ignore ((xen_msr_action_t)(1UL))
#ifdef CONFIG_XEN
/*** This should go into a Xen-specific header file ***/
/*
* The actual calling convention for the asm_xen_ function is:
* Input:
* %rax - value (full 64-bit value, do not read from %edx)
* %ecx - MSR number
* Output:
* %esi - optionally clobbered
* all other registers preserved
* On error, invoke the trap handler at the stack pointer using
* indirect trapping.
*/
void asm_xen_wrmsrns_general(void);
void asm_xen_wrmsrns_perf(void);
static __must_inline xen_msr_action_t xen_wrmsrns_action(uint32_t msr)
{
if (!__builtin_constant_p(msr))
return asm_xen_wrmsrns_general;
switch (msr) {
case 0x1234:
case 0x5678:
return asm_xen_wrmsrns_perf;
case 0x78:
case 0x89:
return xen_msr_ignore;
default:
return xen_msr_native;
}
}
#else
static __must_inline xen_msr_action_t xen_msr_action(uint32_t msr)
{
return xen_msr_native;
}
#endif
#define EX_WRMSR(from,to) \
_ASM_EXTABLE_TYPE(from, to, EX_TYPE_WRMSR, 0)
#define EX_WRMSR_SAFE(from,to) \
_ASM_EXTABLE_TYPE(from, to, EX_TYPE_WRMSR_SAFE, 0)
/*
* XXX: is ASM_CALL_CONSTRAINT compatible with asm goto? Perhaps "memory"
* takes care of the problem without it?
*/
static __must_inline void wrmsrns_variable(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr);
uint32_t hi = val >> 32;
if (xen_what == xen_msr_native) {
asm_inline volatile(
"1:\n"
ALTERNATIVE("ds wrmsr",
"wrmsrns",
X86_FEATURE_WRMSRNS)
"2:\n"
EX_WRMSR(1b,2b)
: : "a" (val), "d" (hi), "c" (msr),
: "memory");
} else {
asm_inline volatile(
"1:\n"
ALTERNATIVE_2("ds wrmsr",
"wrmsrns",
X86_FEATURE_WRMSRNS,
"call %c[xen]",
X86_FEATURE_XENPV)
"2:\n"
EX_WRMSR(1b,2b)
: "+d" (hi), ASM_CALL_CONSTRAINT
: [val] "a" (val), "c" (msr), [xen] "i" (xen_what)
: "memory");
}
}
static __must_inline bool wrmsrns_variable_safe(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr);
const uint32_t hi = val >> 32;
if (xen_what == xen_msr_native) {
asm_inline volatile goto(
"1:\n"
ALTERNATIVE("ds wrmsr",
"wrmsrns",
X86_FEATURE_WRMSRNS)
EX_WRMSR_SAFE(1b,%l[badmsr])
: : [val] "a" (val), "d" (hi), [msr] "c" (msr),
: "memory"
: badmsr);
} else {
/*
* Compute %edx inline to avoid problems with older
* gccs that did not allow output constraints in asm goto
* (since inputs and clobbers can't overlap)
*/
asm_inline volatile goto(
ALTERNATIVE_2("1: mov %%rax,%%rdx; shr $32,%%rdx; "
"2: ds wrmsr"
"mov %%rax,%%rdx; shr $32,%%rdx; "
"wrmsrns",
X86_FEATURE_WRMSRNS,
"call %c[xen]",
X86_FEATURE_XENPV)
EX_WRMSR_SAFE(1b,%l[badmsr]) /* For Xen */
EX_WRMSR_SAFE(2b,%l[badmsr]) /* For WRMSR(NS) */
: ASM_CALL_CONSTRAINT
: [val] "a" (val), [msr] "c" (msr), [xen] "i" (xen_what)
: "memory", "rdx"
: badmsr);
}
return false;
badmsr:
__cold;
return true;
}
#define WRMSRNS_IMM " .insn VEX.128.F3.M7.W0 0xf6 /0, %[val], %[msr] {:u32}\n"
static __must_inline void wrmsrns_constant(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr, safe);
/*
* Compute %edx inline so the space can be reused by the
* immediate instruction forms (9 bytes long.)
*/
if (xen_what == xen_msr_native) {
asm_inline volatile(
ALTERNATIVE_2("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns",
X86_FEATURE_WRMSRNS,
WRMSRNS_IMM,
X86_FEATURE_MSR_IMM)
"3:\n"
EX_WRMSR(1b,3b) /* For WRMSRNS immediate */
EX_WRMSR(2b,3b) /* For WRMSR(NS) */
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx");
} else if (xen_what == xen_msr_ignore) {
asm_inline volatile(
ALTERNATIVE_3("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns",
X86_FEATURE_WRMSRNS,
WRMSRNS_IMM,
X86_FEATURE_MSR_IMM,
"",
X86_FEATURE_XENPV)
"3:\n"
EX_WRMSR(1b,3b) /* For WRMSRNS immediate */
EX_WRMSR(2b,3b) /* For WRMSR(NS) */
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx");
} else {
asm_inline volatile(
ALTERNATIVE_2("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns",
X86_FEATURE_WRMSRNS,
WRMSRNS_IMM,
X86_FEATURE_MSR_IMM)
"3:\n"
EX_WRMSR(1b,3b) /* For Xen and WRMSRNS immediate */
EX_WRMSR(2b,3b) /* For WRMSRNS and WRMSR */
: ASM_CALL_CONSTRAINT
: [val] "a" (val), "c" (msr), [msr] "i" (msr),
[xen] "i" (xen_what)
: "memory", "edx");
}
return err;
}
static __must_inline bool wrmsrns_constant_safe(uint32_t msr, uint64_t val)
{
const xen_msr_action_t xen_what = xen_msr_action(msr, safe);
if (xen_what == xen_msr_native) {
asm_inline volatile goto(
ALTERNATIVE_2("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns",
X86_FEATURE_WRMSRNS,
WRMSRNS_IMM,
X86_FEATURE_MSR_IMM)
EX_WRMSR_SAFE(1b,%l[badmsr]) /* For WRMSRNS immediate */
EX_WRMSR_SAFE(2b,%l[badmsr]) /* For WRMSR(NS) */
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx"
: badmsr);
} else if (xen_what == xen_msr_ignore) {
asm_inline volatile goto(
"1:\n"
ALTERNATIVE_3("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM,
"", X86_FEATURE_XENPV)
EX_WRMSR_SAFE(1b,%l[badmsr]) /* For WRMSRNS immediate */
EX_WRMSR_SAFE(2b,%l[badmsr]) /* For WRMSR(NS) */
: "+r" (err)
: : [val] "a" (val), "c" (msr), [msr] "i" (msr)
: "memory", "edx"
: badmsr);
} else {
asm_inline volatile goto(
ALTERNATIVE_3("1: mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"2: ds wrmsr",
"mov %%rax,%%rdx; "
"shr $32,%%rdx; "
"wrmsrns", X86_FEATURE_WRMSRNS,
WRMSRNS_IMM, X86_FEATURE_MSR_IMM,
"call %c[xen]", X86_FEATURE_XENPV)
EX_WRMSR_SAFE(1b,%l[badmsr]) /* For Xen/WRMSRNS imm */
EX_WRMSR_SAFE(2b,%l[badmsr]) /* For WRMSR(NS) */
: ASM_CALL_CONSTRAINT
: [val] "a" (val), "c" (msr), [msr] "i" (msr),
[xen] "i" (xen_what)
: "memory", "edx"
: badmsr);
}
return false;
badmsr:
__cold;
return true;
}
static inline void wrmsrns(uint32_t msr, uint64_t val)
{
if (__builtin_constant_p(msr))
wrmsrns_constant(msr, val);
else
wrmsrns_variable(msr, val);
}
static inline bool wrmsrns_safe(uint32_t msr, uint64_t val)
{
if (__builtin_constant_p(msr))
return wrmsrns_constant_safe(msr, val);
else
return wrmsrns_variable_safe(msr, val);
}
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-10-23 23:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-23 21:31 RFC, untested: handing of MSR immediates and MSRs on Xen H. Peter Anvin
2024-10-23 21:34 ` H. Peter Anvin
2024-10-23 22:08 ` Uros Bizjak
2024-10-23 23:05 ` H. Peter Anvin
2024-10-23 21:52 ` H. Peter Anvin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®