|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 01/45] xen: arm: do not panic when failing to translate a guest address
On Wed, 23 Jan 2013, Ian Campbell wrote:
> The gva_to_{par,ipa} functions currently panic if the guest address
> cannot be translated. Often the input comes from the guest so
> panicing the host is a bit harsh!
>
> Change the API of those functions to allow them to return a failure
> and plumb it through where it is used.
>
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
I think I have already acked this patch
> xen/arch/arm/guestcopy.c | 30 +++++++++++++++++++----
> xen/arch/arm/kernel.c | 15 +++++++++--
> xen/arch/arm/traps.c | 49 ++++++++++++++++----------------------
> xen/include/asm-arm/mm.h | 9 ++++--
> xen/include/asm-arm/page.h | 29 +++++++++-------------
> xen/include/asm-arm/processor.h | 2 +-
> 6 files changed, 76 insertions(+), 58 deletions(-)
>
> diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
> index d9eb7ac..5504e19 100644
> --- a/xen/arch/arm/guestcopy.c
> +++ b/xen/arch/arm/guestcopy.c
> @@ -12,10 +12,16 @@ unsigned long raw_copy_to_guest(void *to, const void
> *from, unsigned len)
>
> while ( len )
> {
> - paddr_t g = gvirt_to_maddr((uint32_t) to);
> - void *p = map_domain_page(g>>PAGE_SHIFT);
> + int rc;
> + paddr_t g;
> + void *p;
> unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
>
> + rc = gvirt_to_maddr((uint32_t) to, &g);
> + if ( rc )
> + return rc;
> +
> + p = map_domain_page(g>>PAGE_SHIFT);
> p += offset;
> memcpy(p, from, size);
>
> @@ -36,10 +42,16 @@ unsigned long raw_clear_guest(void *to, unsigned len)
>
> while ( len )
> {
> - paddr_t g = gvirt_to_maddr((uint32_t) to);
> - void *p = map_domain_page(g>>PAGE_SHIFT);
> + int rc;
> + paddr_t g;
> + void *p;
> unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
>
> + rc = gvirt_to_maddr((uint32_t) to, &g);
> + if ( rc )
> + return rc;
> +
> + p = map_domain_page(g>>PAGE_SHIFT);
> p += offset;
> memset(p, 0x00, size);
>
> @@ -56,10 +68,16 @@ unsigned long raw_copy_from_guest(void *to, const void
> __user *from, unsigned le
> {
> while ( len )
> {
> - paddr_t g = gvirt_to_maddr((uint32_t) from & PAGE_MASK);
> - void *p = map_domain_page(g>>PAGE_SHIFT);
> + int rc;
> + paddr_t g;
> + void *p;
> unsigned size = min(len, (unsigned)(PAGE_SIZE - ((unsigned)from &
> (~PAGE_MASK))));
>
> + rc = gvirt_to_maddr((uint32_t) from & PAGE_MASK, &g);
> + if ( rc )
> + return rc;
> +
> + p = map_domain_page(g>>PAGE_SHIFT);
> p += ((unsigned long)from & (~PAGE_MASK));
>
> memcpy(to, p, size);
> diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
> index 2f7a9ff..143b9f6 100644
> --- a/xen/arch/arm/kernel.c
> +++ b/xen/arch/arm/kernel.c
> @@ -76,12 +76,21 @@ static void kernel_zimage_load(struct kernel_info *info)
> paddr, load_addr, load_addr + len);
> for ( offs = 0; offs < len; )
> {
> - paddr_t s, l, ma = gvirt_to_maddr(load_addr + offs);
> - void *dst = map_domain_page(ma>>PAGE_SHIFT);
> -
> + int rc;
> + paddr_t s, l, ma;
> + void *dst;
> s = offs & ~PAGE_MASK;
> l = min(PAGE_SIZE - s, len);
>
> + rc = gvirt_to_maddr(load_addr + offs, &ma);
> + if ( rc )
> + {
> + panic("\nUnable to map translate guest address\n");
> + return;
> + }
> +
> + dst = map_domain_page(ma>>PAGE_SHIFT);
> +
> copy_from_paddr(dst + s, paddr + offs, l, attr);
>
> unmap_domain_page(dst);
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 8afcf0c..0a1c483 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -200,32 +200,22 @@ static const char *fsc_level_str(int level)
> }
> }
>
> -void panic_PAR(uint64_t par, const char *when)
> +void panic_PAR(uint64_t par)
> {
> - if ( par & PAR_F )
> - {
> - const char *msg;
> - int level = -1;
> - int stage = par & PAR_STAGE2 ? 2 : 1;
> - int second_in_first = !!(par & PAR_STAGE21);
> -
> - msg = decode_fsc( (par&PAR_FSC_MASK) >> PAR_FSC_SHIFT, &level);
> -
> - printk("PAR: %010"PRIx64": %s stage %d%s%s\n",
> - par, msg,
> - stage,
> - second_in_first ? " during second stage lookup" : "",
> - fsc_level_str(level));
> - }
> - else
> - {
> - printk("PAR: %010"PRIx64": paddr:%010"PRIx64
> - " attr %"PRIx64" sh %"PRIx64" %s\n",
> - par, par & PADDR_MASK, par >> PAR_MAIR_SHIFT,
> - (par & PAR_SH_MASK) >> PAR_SH_SHIFT,
> - (par & PAR_NS) ? "Non-Secure" : "Secure");
> - }
> - panic("Error during %s-to-physical address translation\n", when);
> + const char *msg;
> + int level = -1;
> + int stage = par & PAR_STAGE2 ? 2 : 1;
> + int second_in_first = !!(par & PAR_STAGE21);
> +
> + msg = decode_fsc( (par&PAR_FSC_MASK) >> PAR_FSC_SHIFT, &level);
> +
> + printk("PAR: %010"PRIx64": %s stage %d%s%s\n",
> + par, msg,
> + stage,
> + second_in_first ? " during second stage lookup" : "",
> + fsc_level_str(level));
> +
> + panic("Error during Hypervisor-to-physical address translation\n");
> }
>
> struct reg_ctxt {
> @@ -721,7 +711,7 @@ static void do_trap_data_abort_guest(struct cpu_user_regs
> *regs,
> struct hsr_dabt dabt)
> {
> const char *msg;
> - int level = -1;
> + int rc, level = -1;
> mmio_info_t info;
>
> info.dabt = dabt;
> @@ -730,7 +720,9 @@ static void do_trap_data_abort_guest(struct cpu_user_regs
> *regs,
> if (dabt.s1ptw)
> goto bad_data_abort;
>
> - info.gpa = gva_to_ipa(info.gva);
> + rc = gva_to_ipa(info.gva, &info.gpa);
> + if ( rc == -EFAULT )
> + goto bad_data_abort;
>
> if (handle_mmio(&info))
> {
> @@ -742,6 +734,7 @@ bad_data_abort:
>
> msg = decode_fsc( dabt.dfsc, &level);
>
> + /* XXX inject a suitable fault into the guest */
> printk("Guest data abort: %s%s%s\n"
> " gva=%"PRIx32"\n",
> msg, dabt.s1ptw ? " S2 during S1" : "",
> @@ -761,7 +754,7 @@ bad_data_abort:
> else
> dump_guest_s1_walk(current->domain, info.gva);
> show_execution_state(regs);
> - panic("Unhandled guest data abort\n");
> + domain_crash_synchronous();
> }
>
> asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index 146507e..4175e4d 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -191,10 +191,13 @@ static inline void *maddr_to_virt(paddr_t ma)
> return (void *)(unsigned long) ma + XENHEAP_VIRT_START;
> }
>
> -static inline paddr_t gvirt_to_maddr(uint32_t va)
> +static inline int gvirt_to_maddr(uint32_t va, paddr_t *pa)
> {
> - uint64_t par = gva_to_par(va);
> - return (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va &
> ~PAGE_MASK);
> + uint64_t par = gva_to_ma_par(va);
> + if ( par & PAR_F )
> + return -EFAULT;
> + *pa = (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va & ~PAGE_MASK);
> + return 0;
> }
>
> /* Convert between Xen-heap virtual addresses and machine addresses. */
> diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
> index d89261e..067345e 100644
> --- a/xen/include/asm-arm/page.h
> +++ b/xen/include/asm-arm/page.h
> @@ -2,6 +2,7 @@
> #define __ARM_PAGE_H__
>
> #include <xen/config.h>
> +#include <xen/errno.h>
> #include <public/xen.h>
> #include <asm/processor.h>
>
> @@ -362,13 +363,13 @@ static inline uint64_t va_to_par(uint32_t va)
> if ( par & PAR_F )
> {
> dump_hyp_walk(va);
> - panic_PAR(par, "Hypervisor");
> + panic_PAR(par);
> }
> return par;
> }
>
> /* Ask the MMU to translate a Guest VA for us */
> -static inline uint64_t __gva_to_par(uint32_t va)
> +static inline uint64_t gva_to_ma_par(uint32_t va)
> {
> uint64_t par, tmp;
> tmp = READ_CP64(PAR);
> @@ -378,15 +379,7 @@ static inline uint64_t __gva_to_par(uint32_t va)
> WRITE_CP64(tmp, PAR);
> return par;
> }
> -static inline uint64_t gva_to_par(uint32_t va)
> -{
> - uint64_t par = __gva_to_par(va);
> - /* It is not OK to call this with an invalid VA */
> - /* XXX harsh for a guest address... */
> - if ( par & PAR_F ) panic_PAR(par, "Guest");
> - return par;
> -}
> -static inline uint64_t __gva_to_ipa(uint32_t va)
> +static inline uint64_t gva_to_ipa_par(uint32_t va)
> {
> uint64_t par, tmp;
> tmp = READ_CP64(PAR);
> @@ -396,14 +389,16 @@ static inline uint64_t __gva_to_ipa(uint32_t va)
> WRITE_CP64(tmp, PAR);
> return par;
> }
> -static inline uint64_t gva_to_ipa(uint32_t va)
> +
> +static inline int gva_to_ipa(uint32_t va, paddr_t *paddr)
> {
> - uint64_t par = __gva_to_ipa(va);
> - /* It is not OK to call this with an invalid VA */
> - /* XXX harsh for a guest address... */
> - if ( par & PAR_F ) panic_PAR(par, "Guest");
> - return (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va &
> ~PAGE_MASK);
> + uint64_t par = gva_to_ipa_par(va);
> + if ( par & PAR_F )
> + return -EFAULT;
> + *paddr = (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va &
> ~PAGE_MASK);
> + return 0;
> }
> +
> /* Bits in the PAR returned by va_to_par */
> #define PAR_FAULT 0x1
>
> diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
> index e0c0beb..0c94f6b 100644
> --- a/xen/include/asm-arm/processor.h
> +++ b/xen/include/asm-arm/processor.h
> @@ -231,7 +231,7 @@ union hsr {
> #ifndef __ASSEMBLY__
> extern uint32_t hyp_traps_vector[8];
>
> -void panic_PAR(uint64_t par, const char *when);
> +void panic_PAR(uint64_t par);
>
> void show_execution_state(struct cpu_user_regs *regs);
> void show_registers(struct cpu_user_regs *regs);
> --
> 1.7.2.5
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |