Mailing List Archive

[xen master] x86/pv: Improve dom0_update_physmap() with CONFIG_SPECULATIVE_HARDEN_BRANCH
commit 97f9861b8f22aaa28cb1f4588f2e6fc9b173ec90
Author: Andrew Cooper <andrew.cooper3@citrix.com>
AuthorDate: Thu Oct 29 19:53:28 2020 +0000
Commit: Andrew Cooper <andrew.cooper3@citrix.com>
CommitDate: Fri Apr 16 14:43:28 2021 +0100

x86/pv: Improve dom0_update_physmap() with CONFIG_SPECULATIVE_HARDEN_BRANCH

dom0_update_physmap() is mostly called in two tight loops, where the lfences
hidden in is_pv_32bit_domain() have a substantial impact.

None of the boot time construction needs protection against malicious
speculation, so use a local variable and calculate is_pv_32bit_domain() just
once.

Reformat the some of the code for legibility, now that the volume has reduced,
and removal of some gratuitous negations.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
xen/arch/x86/pv/dom0_build.c | 52 +++++++++++++++++++---------------------
xen/arch/x86/pv/shim.c | 6 +++--
xen/include/asm-x86/dom0_build.h | 2 +-
3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index 265f56a3f8..e0801a9e6d 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -31,10 +31,10 @@
#define L3_PROT (BASE_PROT|_PAGE_DIRTY)
#define L4_PROT (BASE_PROT|_PAGE_DIRTY)

-void __init dom0_update_physmap(struct domain *d, unsigned long pfn,
+void __init dom0_update_physmap(bool compat, unsigned long pfn,
unsigned long mfn, unsigned long vphysmap_s)
{
- if ( !is_pv_32bit_domain(d) )
+ if ( !compat )
((unsigned long *)vphysmap_s)[pfn] = mfn;
else
((unsigned int *)vphysmap_s)[pfn] = mfn;
@@ -289,7 +289,7 @@ int __init dom0_construct_pv(struct domain *d,
char *cmdline)
{
int i, rc, order, machine;
- bool compatible;
+ bool compatible, compat;
struct cpu_user_regs *regs;
unsigned long pfn, mfn;
unsigned long nr_pages;
@@ -380,6 +380,8 @@ int __init dom0_construct_pv(struct domain *d,
}
#endif

+ compat = is_pv_32bit_domain(d);
+
if ( elf_64bit(&elf) && machine == EM_X86_64 )
compatible = true;

@@ -463,9 +465,9 @@ int __init dom0_construct_pv(struct domain *d,
vinitrd_end = vinitrd_start + initrd_len;
vphysmap_start = round_pgup(vinitrd_end);
}
- vphysmap_end = vphysmap_start + (nr_pages * (!is_pv_32bit_domain(d) ?
- sizeof(unsigned long) :
- sizeof(unsigned int)));
+
+ vphysmap_end = vphysmap_start +
+ (nr_pages * (compat ? sizeof(unsigned int) : sizeof(unsigned long)));
if ( parms.p2m_base != UNSET_ADDR )
vphysmap_end = vphysmap_start;
vstartinfo_start = round_pgup(vphysmap_end);
@@ -496,9 +498,9 @@ int __init dom0_construct_pv(struct domain *d,
#define NR(_l,_h,_s) \
(((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
((_l) & ~((1UL<<(_s))-1))) >> (_s))
- if ( (!is_pv_32bit_domain(d) + /* # L4 */
+ if ( (!compat + /* # L4 */
NR(v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
- (!is_pv_32bit_domain(d) ?
+ (!compat ?
NR(v_start, v_end, L3_PAGETABLE_SHIFT) : /* # L2 */
4) + /* # compat L2 */
NR(v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
@@ -600,23 +602,22 @@ int __init dom0_construct_pv(struct domain *d,
mpt_alloc -= PAGE_ALIGN(initrd_len);

/* Overlap with Xen protected area? */
- if ( !is_pv_32bit_domain(d) ?
- ((v_start < HYPERVISOR_VIRT_END) &&
- (v_end > HYPERVISOR_VIRT_START)) :
- (v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
+ if ( compat
+ ? v_end > HYPERVISOR_COMPAT_VIRT_START(d)
+ : (v_start < HYPERVISOR_VIRT_END) && (v_end > HYPERVISOR_VIRT_START) )
{
printk("DOM0 image overlaps with Xen private area.\n");
rc = -EINVAL;
goto out;
}

- if ( is_pv_32bit_domain(d) )
+ if ( compat )
{
v->arch.pv.failsafe_callback_cs = FLAT_COMPAT_KERNEL_CS;
v->arch.pv.event_callback_cs = FLAT_COMPAT_KERNEL_CS;
}

- if ( !is_pv_32bit_domain(d) )
+ if ( !compat )
{
maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l4_page_table;
l4start = l4tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;
@@ -677,8 +678,7 @@ int __init dom0_construct_pv(struct domain *d,
mfn = pfn++;
else
mfn = initrd_mfn++;
- *l1tab = l1e_from_pfn(mfn, (!is_pv_32bit_domain(d) ?
- L1_PROT : COMPAT_L1_PROT));
+ *l1tab = l1e_from_pfn(mfn, compat ? COMPAT_L1_PROT : L1_PROT);
l1tab++;

page = mfn_to_page(_mfn(mfn));
@@ -687,7 +687,7 @@ int __init dom0_construct_pv(struct domain *d,
BUG();
}

- if ( is_pv_32bit_domain(d) )
+ if ( compat )
{
l2_pgentry_t *l2t;

@@ -806,7 +806,7 @@ int __init dom0_construct_pv(struct domain *d,
if ( pfn > REVERSE_START && (vinitrd_start || pfn < initrd_pfn) )
mfn = alloc_epfn - (pfn - REVERSE_START);
#endif
- dom0_update_physmap(d, pfn, mfn, vphysmap_start);
+ dom0_update_physmap(compat, pfn, mfn, vphysmap_start);
if ( !(pfn & 0xfffff) )
process_pending_softirqs();
}
@@ -818,12 +818,12 @@ int __init dom0_construct_pv(struct domain *d,
BUG_ON(SHARED_M2P(get_gpfn_from_mfn(mfn)));
if ( get_gpfn_from_mfn(mfn) >= count )
{
- BUG_ON(is_pv_32bit_domain(d));
+ BUG_ON(compat);
if ( !page->u.inuse.type_info &&
!get_page_and_type(page, d, PGT_writable_page) )
BUG();

- dom0_update_physmap(d, pfn, mfn, vphysmap_start);
+ dom0_update_physmap(compat, pfn, mfn, vphysmap_start);
++pfn;
if ( !(pfn & 0xfffff) )
process_pending_softirqs();
@@ -843,7 +843,7 @@ int __init dom0_construct_pv(struct domain *d,
#ifndef NDEBUG
#define pfn (nr_pages - 1 - (pfn - (alloc_epfn - alloc_spfn)))
#endif
- dom0_update_physmap(d, pfn, mfn, vphysmap_start);
+ dom0_update_physmap(compat, pfn, mfn, vphysmap_start);
#undef pfn
page++; pfn++;
if ( !(pfn & 0xfffff) )
@@ -878,7 +878,7 @@ int __init dom0_construct_pv(struct domain *d,
vphysmap_start, si);

#ifdef CONFIG_COMPAT
- if ( is_pv_32bit_domain(d) )
+ if ( compat )
xlat_start_info(si, pv_shim ? XLAT_start_info_console_domU
: XLAT_start_info_console_dom0);
#endif
@@ -899,11 +899,9 @@ int __init dom0_construct_pv(struct domain *d,
*/
regs = &v->arch.user_regs;
regs->ds = regs->es = regs->fs = regs->gs =
- !is_pv_32bit_domain(d) ? FLAT_KERNEL_DS : FLAT_COMPAT_KERNEL_DS;
- regs->ss = (!is_pv_32bit_domain(d) ?
- FLAT_KERNEL_SS : FLAT_COMPAT_KERNEL_SS);
- regs->cs = (!is_pv_32bit_domain(d) ?
- FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS);
+ (compat ? FLAT_COMPAT_KERNEL_DS : FLAT_KERNEL_DS);
+ regs->ss = (compat ? FLAT_COMPAT_KERNEL_SS : FLAT_KERNEL_SS);
+ regs->cs = (compat ? FLAT_COMPAT_KERNEL_CS : FLAT_KERNEL_CS);
regs->rip = parms.virt_entry;
regs->rsp = vstack_end;
regs->rsi = vstartinfo_start;
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index 92cb1adeed..1b86fc247e 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -204,6 +204,7 @@ void __init pv_shim_setup_dom(struct domain *d, l4_pgentry_t *l4start,
unsigned long console_va, unsigned long vphysmap,
start_info_t *si)
{
+ bool compat = is_pv_32bit_domain(d);
hypercall_table_t *rw_pv_hypercall_table;
uint64_t param = 0;
long rc;
@@ -217,7 +218,8 @@ void __init pv_shim_setup_dom(struct domain *d, l4_pgentry_t *l4start,
{ \
share_xen_page_with_guest(mfn_to_page(_mfn(param)), d, SHARE_rw); \
replace_va_mapping(d, l4start, va, _mfn(param)); \
- dom0_update_physmap(d, PFN_DOWN((va) - va_start), param, vphysmap); \
+ dom0_update_physmap(compat, \
+ PFN_DOWN((va) - va_start), param, vphysmap); \
} \
else \
{ \
@@ -244,7 +246,7 @@ void __init pv_shim_setup_dom(struct domain *d, l4_pgentry_t *l4start,
si->console.domU.mfn = mfn_x(console_mfn);
share_xen_page_with_guest(mfn_to_page(console_mfn), d, SHARE_rw);
replace_va_mapping(d, l4start, console_va, console_mfn);
- dom0_update_physmap(d, (console_va - va_start) >> PAGE_SHIFT,
+ dom0_update_physmap(compat, (console_va - va_start) >> PAGE_SHIFT,
mfn_x(console_mfn), vphysmap);
consoled_set_ring_addr(page);
}
diff --git a/xen/include/asm-x86/dom0_build.h b/xen/include/asm-x86/dom0_build.h
index 0b797b5806..a5f8c9e67f 100644
--- a/xen/include/asm-x86/dom0_build.h
+++ b/xen/include/asm-x86/dom0_build.h
@@ -26,7 +26,7 @@ int dom0_construct_pvh(struct domain *d, const module_t *image,
unsigned long dom0_paging_pages(const struct domain *d,
unsigned long nr_pages);

-void dom0_update_physmap(struct domain *d, unsigned long pfn,
+void dom0_update_physmap(bool compat, unsigned long pfn,
unsigned long mfn, unsigned long vphysmap_s);

#endif /* _DOM0_BUILD_H_ */
--
generated by git-patchbot for /home/xen/git/xen.git#master