Message ID | 20170615110516.448-8-proskurin@sec.in.tum.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 15/06/17 12:05, Sergej Proskurin wrote: > The function p2m_mem_access_check_and_get_page in mem_access.c > translates a gva to an ipa by means of the hardware functionality of the > ARM architecture. This is implemented in the function gva_to_ipa. If > mem_access is active, hardware-based gva to ipa translation might fail, > as gva_to_ipa uses the guest's translation tables, access to which might > be restricted by the active VTTBR. To address this issue, in this commit > we add a software-based guest-page-table walk, which will be used by the > function p2m_mem_access_check_and_get_page perform the gva to ipa > translation in software in one of the following commits. > > Note: The introduced function guest_walk_tables assumes that the domain, > the gva of which is to be translated, is running on the currently active > vCPU. To walk the guest's page tables on a different vCPU, the following > registers would need to be loaded: TCR_EL1, TTBR0_EL1, TTBR1_EL1, and > SCTLR_EL1. > > Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de> > --- > Cc: Stefano Stabellini <sstabellini@kernel.org> > Cc: Julien Grall <julien.grall@arm.com> > --- > v2: Rename p2m_gva_to_ipa to p2m_walk_gpt and move it to p2m.c. > > Move the functionality responsible for walking long-descriptor based > translation tables out of the function p2m_walk_gpt. Also move out > the long-descriptor based translation out of this commit. > > Change function parameters in order to return access access rights > to a requested gva. > > Cosmetic fixes. > > v3: Rename the introduced functions to guest_walk_(tables|sd|ld) and > move the implementation to guest_copy.(c|h). > > Set permissions in guest_walk_tables also if the MMU is disabled. > > Change the function parameter of type "struct p2m_domain *" to > "struct vcpu *" in the functions guest_walk_(tables|sd|ld). > --- > xen/arch/arm/Makefile | 1 + > xen/arch/arm/guest_walk.c | 92 ++++++++++++++++++++++++++++++++++++++++ > xen/include/asm-arm/guest_walk.h | 19 +++++++++ > 3 files changed, 112 insertions(+) > create mode 100644 xen/arch/arm/guest_walk.c > create mode 100644 xen/include/asm-arm/guest_walk.h > > diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile > index 49e1fb2f84..282d2c2949 100644 > --- a/xen/arch/arm/Makefile > +++ b/xen/arch/arm/Makefile > @@ -21,6 +21,7 @@ obj-$(CONFIG_HAS_GICV3) += gic-v3.o > obj-$(CONFIG_HAS_ITS) += gic-v3-its.o > obj-$(CONFIG_HAS_ITS) += gic-v3-lpi.o > obj-y += guestcopy.o > +obj-y += guest_walk.o > obj-y += hvm.o > obj-y += io.o > obj-y += irq.o > diff --git a/xen/arch/arm/guest_walk.c b/xen/arch/arm/guest_walk.c > new file mode 100644 > index 0000000000..f2f3533665 > --- /dev/null > +++ b/xen/arch/arm/guest_walk.c > @@ -0,0 +1,92 @@ > +/* > + * Guest page table walk > + * Copyright (c) 2017 Sergej Proskurin <proskurin@sec.in.tum.de> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for > + * more details. > + * > + * 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 <xen/sched.h> > + > +/* > + * The function guest_walk_sd translates a given GVA into an IPA using the > + * short-descriptor translation table format in software. This function assumes > + * that the domain is running on the currently active vCPU. To walk the guest's > + * page table on a different vCPU, the following registers would need to be > + * loaded: TCR_EL1, TTBR0_EL1, TTBR1_EL1, and SCTLR_EL1. > + */ > +static int guest_walk_sd(struct domain *d, As I said in v2, it should be a vcpu and not a domain here because page-table are per-vCPU. > + vaddr_t gva, paddr_t *ipa, > + unsigned int *perms) > +{ > + /* Not implemented yet. */ > + return -EFAULT; > +} > + > +/* > + * The function guest_walk_ld translates a given GVA into an IPA using the > + * long-descriptor translation table format in software. This function assumes > + * that the domain is running on the currently active vCPU. To walk the guest's > + * page table on a different vCPU, the following registers would need to be > + * loaded: TCR_EL1, TTBR0_EL1, TTBR1_EL1, and SCTLR_EL1. > + */ > +static int guest_walk_ld(struct domain *d, > + vaddr_t gva, paddr_t *ipa, > + unsigned int *perms) Ditto. > +{ > + /* Not implemented yet. */ > + return -EFAULT; > +} > + > +int guest_walk_tables(const struct vcpu *v, vaddr_t gva, > + paddr_t *ipa, unsigned int *perms) > +{ > + uint32_t sctlr = READ_SYSREG(SCTLR_EL1); > + register_t tcr = READ_SYSREG(TCR_EL1); > + struct domain *d = v->domain; > + unsigned int _perms = GV2M_READ; > + > + /* We assume that the domain is running on the currently active domain. */ > + if ( v != current ) > + return -EFAULT; > + > + /* Allow perms to be NULL. */ > + perms = perms ?: &_perms; > + > + /* If the MMU is disabled, there is no need to translate the gva. */ > + if ( !(sctlr & SCTLR_M) ) > + { > + *ipa = gva; > + > + /* Memory can be accessed without any restrictions. */ > + *perms = GV2M_READ|GV2M_WRITE|GV2M_EXEC; > + > + return 0; > + } > + > + if ( is_32bit_domain(d) ) > + { > + if ( !(tcr & TTBCR_EAE) ) > + return guest_walk_sd(d, gva, ipa, perms); > + } > + > + return guest_walk_ld(d, gva, ipa, perms); > +} > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/include/asm-arm/guest_walk.h b/xen/include/asm-arm/guest_walk.h > new file mode 100644 > index 0000000000..4ed8476e08 > --- /dev/null > +++ b/xen/include/asm-arm/guest_walk.h > @@ -0,0 +1,19 @@ > +#ifndef _XEN_GUEST_WALK_H > +#define _XEN_GUEST_WALK_H > + > +/* Walk the guest's page tables in software. */ > +int guest_walk_tables(const struct vcpu *v, > + vaddr_t gva, > + paddr_t *ipa, > + unsigned int *perms); > + > +#endif /* _XEN_GUEST_WALK_H */ > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > Cheers,
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 49e1fb2f84..282d2c2949 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_HAS_GICV3) += gic-v3.o obj-$(CONFIG_HAS_ITS) += gic-v3-its.o obj-$(CONFIG_HAS_ITS) += gic-v3-lpi.o obj-y += guestcopy.o +obj-y += guest_walk.o obj-y += hvm.o obj-y += io.o obj-y += irq.o diff --git a/xen/arch/arm/guest_walk.c b/xen/arch/arm/guest_walk.c new file mode 100644 index 0000000000..f2f3533665 --- /dev/null +++ b/xen/arch/arm/guest_walk.c @@ -0,0 +1,92 @@ +/* + * Guest page table walk + * Copyright (c) 2017 Sergej Proskurin <proskurin@sec.in.tum.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * 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 <xen/sched.h> + +/* + * The function guest_walk_sd translates a given GVA into an IPA using the + * short-descriptor translation table format in software. This function assumes + * that the domain is running on the currently active vCPU. To walk the guest's + * page table on a different vCPU, the following registers would need to be + * loaded: TCR_EL1, TTBR0_EL1, TTBR1_EL1, and SCTLR_EL1. + */ +static int guest_walk_sd(struct domain *d, + vaddr_t gva, paddr_t *ipa, + unsigned int *perms) +{ + /* Not implemented yet. */ + return -EFAULT; +} + +/* + * The function guest_walk_ld translates a given GVA into an IPA using the + * long-descriptor translation table format in software. This function assumes + * that the domain is running on the currently active vCPU. To walk the guest's + * page table on a different vCPU, the following registers would need to be + * loaded: TCR_EL1, TTBR0_EL1, TTBR1_EL1, and SCTLR_EL1. + */ +static int guest_walk_ld(struct domain *d, + vaddr_t gva, paddr_t *ipa, + unsigned int *perms) +{ + /* Not implemented yet. */ + return -EFAULT; +} + +int guest_walk_tables(const struct vcpu *v, vaddr_t gva, + paddr_t *ipa, unsigned int *perms) +{ + uint32_t sctlr = READ_SYSREG(SCTLR_EL1); + register_t tcr = READ_SYSREG(TCR_EL1); + struct domain *d = v->domain; + unsigned int _perms = GV2M_READ; + + /* We assume that the domain is running on the currently active domain. */ + if ( v != current ) + return -EFAULT; + + /* Allow perms to be NULL. */ + perms = perms ?: &_perms; + + /* If the MMU is disabled, there is no need to translate the gva. */ + if ( !(sctlr & SCTLR_M) ) + { + *ipa = gva; + + /* Memory can be accessed without any restrictions. */ + *perms = GV2M_READ|GV2M_WRITE|GV2M_EXEC; + + return 0; + } + + if ( is_32bit_domain(d) ) + { + if ( !(tcr & TTBCR_EAE) ) + return guest_walk_sd(d, gva, ipa, perms); + } + + return guest_walk_ld(d, gva, ipa, perms); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-arm/guest_walk.h b/xen/include/asm-arm/guest_walk.h new file mode 100644 index 0000000000..4ed8476e08 --- /dev/null +++ b/xen/include/asm-arm/guest_walk.h @@ -0,0 +1,19 @@ +#ifndef _XEN_GUEST_WALK_H +#define _XEN_GUEST_WALK_H + +/* Walk the guest's page tables in software. */ +int guest_walk_tables(const struct vcpu *v, + vaddr_t gva, + paddr_t *ipa, + unsigned int *perms); + +#endif /* _XEN_GUEST_WALK_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */
The function p2m_mem_access_check_and_get_page in mem_access.c translates a gva to an ipa by means of the hardware functionality of the ARM architecture. This is implemented in the function gva_to_ipa. If mem_access is active, hardware-based gva to ipa translation might fail, as gva_to_ipa uses the guest's translation tables, access to which might be restricted by the active VTTBR. To address this issue, in this commit we add a software-based guest-page-table walk, which will be used by the function p2m_mem_access_check_and_get_page perform the gva to ipa translation in software in one of the following commits. Note: The introduced function guest_walk_tables assumes that the domain, the gva of which is to be translated, is running on the currently active vCPU. To walk the guest's page tables on a different vCPU, the following registers would need to be loaded: TCR_EL1, TTBR0_EL1, TTBR1_EL1, and SCTLR_EL1. Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de> --- Cc: Stefano Stabellini <sstabellini@kernel.org> Cc: Julien Grall <julien.grall@arm.com> --- v2: Rename p2m_gva_to_ipa to p2m_walk_gpt and move it to p2m.c. Move the functionality responsible for walking long-descriptor based translation tables out of the function p2m_walk_gpt. Also move out the long-descriptor based translation out of this commit. Change function parameters in order to return access access rights to a requested gva. Cosmetic fixes. v3: Rename the introduced functions to guest_walk_(tables|sd|ld) and move the implementation to guest_copy.(c|h). Set permissions in guest_walk_tables also if the MMU is disabled. Change the function parameter of type "struct p2m_domain *" to "struct vcpu *" in the functions guest_walk_(tables|sd|ld). --- xen/arch/arm/Makefile | 1 + xen/arch/arm/guest_walk.c | 92 ++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/guest_walk.h | 19 +++++++++ 3 files changed, 112 insertions(+) create mode 100644 xen/arch/arm/guest_walk.c create mode 100644 xen/include/asm-arm/guest_walk.h