Files
xen/tools/libxc/xc_core_arm.c
T
Julien Grall 5b5c40c0d1 libxc: introduce a per architecture scratch pfn for temporary grant mapping
The code to initialize the grant table in libxc uses
xc_domain_maximum_gpfn() + 1 to get a guest pfn for mapping the grant
frame and to initialize it.

This solution has two major issues:
    - The check of the return of xc_domain_maximum_gpfn is buggy because
    xen_pfn_t is unsigned and in case of an error -ERRNO is returned.
    Which is never catch with ( pfn <= 0 ).
    - The guest memory layout maybe filled up to the end, i.e
    xc_domain_maximum_gpfn() + 1 gives either 0 or an invalid PFN due to
    hardware limitation.

Futhermore, on ARM, xc_domain_maximum_gpfn() is not implemented and
return -ENOSYS. This will make libxc to use always the same PFN which
may colapse with an already mapped region (see xen/include/public/arch-arm.h
for the layout).

This patch only address the problem for ARM, the x86 version use the same
behavior (ie xc_domain_maximum_gpfn() + 1), as I'm not familiar with Xen x86.

A new function xc_core_arch_get_scratch_gpfn is introduced to be able to
choose the gpfn per architecture.

For the ARM version, we use the GUEST_GNTTAB_GUEST which is the base of
the region by the guest to map the grant table. At the build time,
nothing is mapped there.

At the same time correctly check the return of xc_domain_maximum_gpfn
for x86.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Roger Pau Monné <roger.pau@citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
2015-01-27 16:30:35 +00:00

125 lines
3.5 KiB
C

/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Copyright (c) 2011 Citrix Systems
*
*/
#include "xg_private.h"
#include "xc_core.h"
int
xc_core_arch_gpfn_may_present(struct xc_core_arch_context *arch_ctxt,
unsigned long pfn)
{
/* TODO: memory from DT */
if (pfn >= 0x80000 && pfn < 0x88000)
return 1;
return 0;
}
static int nr_gpfns(xc_interface *xch, domid_t domid)
{
return xc_domain_maximum_gpfn(xch, domid) + 1;
}
int
xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
{
return 1;
}
int
xc_core_arch_memory_map_get(xc_interface *xch, struct xc_core_arch_context *unused,
xc_dominfo_t *info, shared_info_any_t *live_shinfo,
xc_core_memory_map_t **mapp,
unsigned int *nr_entries)
{
unsigned long p2m_size = nr_gpfns(xch, info->domid);
xc_core_memory_map_t *map;
map = malloc(sizeof(*map));
if ( map == NULL )
{
PERROR("Could not allocate memory");
return -1;
}
map->addr = 0;
map->size = ((uint64_t)p2m_size) << PAGE_SHIFT;
*mapp = map;
*nr_entries = 1;
return 0;
}
static int
xc_core_arch_map_p2m_rw(xc_interface *xch, struct domain_info_context *dinfo, xc_dominfo_t *info,
shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m,
unsigned long *pfnp, int rw)
{
errno = ENOSYS;
return -1;
}
int
xc_core_arch_map_p2m(xc_interface *xch, unsigned int guest_width, xc_dominfo_t *info,
shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m,
unsigned long *pfnp)
{
struct domain_info_context _dinfo = { .guest_width = guest_width };
struct domain_info_context *dinfo = &_dinfo;
return xc_core_arch_map_p2m_rw(xch, dinfo, info,
live_shinfo, live_p2m, pfnp, 0);
}
int
xc_core_arch_map_p2m_writable(xc_interface *xch, unsigned int guest_width, xc_dominfo_t *info,
shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m,
unsigned long *pfnp)
{
struct domain_info_context _dinfo = { .guest_width = guest_width };
struct domain_info_context *dinfo = &_dinfo;
return xc_core_arch_map_p2m_rw(xch, dinfo, info,
live_shinfo, live_p2m, pfnp, 1);
}
int
xc_core_arch_get_scratch_gpfn(xc_interface *xch, domid_t domid,
xen_pfn_t *gpfn)
{
/*
* The Grant Table region space is not used until the guest is
* booting. Use the first page for the scratch pfn.
*/
XC_BUILD_BUG_ON(GUEST_GNTTAB_SIZE < XC_PAGE_SIZE);
*gpfn = GUEST_GNTTAB_BASE >> XC_PAGE_SHIFT;
return 0;
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/