mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html. This is the result of: $ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl Where fsf.pl is: #!/usr/bin/perl -w -pi.bak -0777 my $repl = 'If not, see <http://www.gnu.org/licenses/>.'; my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/; my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/; my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/; my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/; my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/; s|$inwt$br$mass|$repl|m; s|$inwt$br$franklin|$repl|m; s|$inwt$br$temple|$repl|m; The only remaining mentions of these addresses are in COPYING files which I haven't touched. Some of the changed files are imports from elsewhere, however filtering them out is tricky, I think it is tolerable to have these files be modified here and then perhaps reverted on the next sync, since it's only 1-2 lines and obvious what is going on. Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
112 lines
3.6 KiB
C
112 lines
3.6 KiB
C
/******************************************************************************
|
|
* xc_pagetab.c
|
|
*
|
|
* Function to translate virtual to physical addresses.
|
|
*
|
|
* 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;
|
|
* version 2.1 of the License.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "xc_private.h"
|
|
#include <xen/hvm/save.h>
|
|
|
|
#define CR0_PG 0x80000000
|
|
#define CR4_PAE 0x20
|
|
#define PTE_PSE 0x80
|
|
#define EFER_LMA 0x400
|
|
|
|
|
|
unsigned long xc_translate_foreign_address(xc_interface *xch, uint32_t dom,
|
|
int vcpu, unsigned long long virt)
|
|
{
|
|
xc_dominfo_t dominfo;
|
|
uint64_t paddr, mask, pte = 0;
|
|
int size, level, pt_levels = 2;
|
|
void *map;
|
|
|
|
if (xc_domain_getinfo(xch, dom, 1, &dominfo) != 1
|
|
|| dominfo.domid != dom)
|
|
return 0;
|
|
|
|
/* What kind of paging are we dealing with? */
|
|
if (dominfo.hvm) {
|
|
struct hvm_hw_cpu ctx;
|
|
if (xc_domain_hvm_getcontext_partial(xch, dom,
|
|
HVM_SAVE_CODE(CPU), vcpu,
|
|
&ctx, sizeof ctx) != 0)
|
|
return 0;
|
|
if (!(ctx.cr0 & CR0_PG))
|
|
return virt >> PAGE_SHIFT;
|
|
pt_levels = (ctx.msr_efer&EFER_LMA) ? 4 : (ctx.cr4&CR4_PAE) ? 3 : 2;
|
|
paddr = ctx.cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull);
|
|
} else {
|
|
unsigned int gwidth;
|
|
vcpu_guest_context_any_t ctx;
|
|
if (xc_vcpu_getcontext(xch, dom, vcpu, &ctx) != 0)
|
|
return 0;
|
|
if (xc_domain_get_guest_width(xch, dom, &gwidth) != 0)
|
|
return 0;
|
|
if (gwidth == 8) {
|
|
pt_levels = 4;
|
|
paddr = (uint64_t)xen_cr3_to_pfn_x86_64(ctx.x64.ctrlreg[3])
|
|
<< PAGE_SHIFT;
|
|
} else {
|
|
pt_levels = 3;
|
|
paddr = (uint64_t)xen_cr3_to_pfn_x86_32(ctx.x32.ctrlreg[3])
|
|
<< PAGE_SHIFT;
|
|
}
|
|
}
|
|
|
|
if (pt_levels == 4) {
|
|
virt &= 0x0000ffffffffffffull;
|
|
mask = 0x0000ff8000000000ull;
|
|
} else if (pt_levels == 3) {
|
|
virt &= 0x00000000ffffffffull;
|
|
mask = 0x0000007fc0000000ull;
|
|
} else {
|
|
virt &= 0x00000000ffffffffull;
|
|
mask = 0x00000000ffc00000ull;
|
|
}
|
|
size = (pt_levels == 2 ? 4 : 8);
|
|
|
|
/* Walk the pagetables */
|
|
for (level = pt_levels; level > 0; level--) {
|
|
paddr += ((virt & mask) >> (xc_ffs64(mask) - 1)) * size;
|
|
map = xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_READ,
|
|
paddr >>PAGE_SHIFT);
|
|
if (!map)
|
|
return 0;
|
|
memcpy(&pte, map + (paddr & (PAGE_SIZE - 1)), size);
|
|
munmap(map, PAGE_SIZE);
|
|
if (!(pte & 1))
|
|
return 0;
|
|
paddr = pte & 0x000ffffffffff000ull;
|
|
if (level == 2 && (pte & PTE_PSE)) {
|
|
mask = ((mask ^ ~-mask) >> 1); /* All bits below first set bit */
|
|
return ((paddr & ~mask) | (virt & mask)) >> PAGE_SHIFT;
|
|
}
|
|
mask >>= (pt_levels == 2 ? 10 : 9);
|
|
}
|
|
return paddr >> PAGE_SHIFT;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-file-style: "BSD"
|
|
* c-basic-offset: 4
|
|
* tab-width: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|