bitkeeper revision 1.1615.1.1 (429c8530L_ZtVuxsQcKwKB3yPuljog)

Subject: PAE support

This patch adds initial support for PAE paging to xen.
This patch does:

 * boot Xen itself with PAE paging enabled.
 * add PAE support to the dom0 domain builder.

Some notes on the design and the changes:

 * There are two new config options: CONFIG_X86_PAE (boolean,
   same name Linux uses to simply things) and
   CONFIG_PAGING_LEVELS (int, possible values are 2,3,4).  I've
   used #if CONFIG_PAGING_LEVELS for stuff which simply depends
   on the number of paging levels in the code common for
   x86-32/64, and CONFIG_X86_PAE for special PAE quirks or
   i386-only stuff.  I've tried to avoid ifdefs if possible
   though, often I rearranged code to make it work in both
   PAE and non-PAE case instead.

 * idle_pg_table:  3rd level is statically initialized, 2nd
   level is contignous in physical and virtual memory, so it can
   be addressed linear (the dom0 builder uses the same trick to
   simplify things a bit btw.).  There are two new symbols:
   idle_pg_table_l3 and idle_pg_table_l2 for the two tables.
   idle_pg_table is aliased to the toplevel page table, i.e.
   idle_pg_table_l3 in PAE mode and idle_pg_table_l2 in non-pae
   mode.  The idle l3 table is actually never ever touched after
   boot, the l2 table is accessed via idle_pg_table_l2 and
   addressed linear in both PAE and non-PAE mode.

 * I've added a "intpte_t" type and a PRIpte define, modeled
   after the C99 inttypes.h header, for page table entries.

Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-05-31 15:39:28 +00:00
1 parent 59f83bdc8f
commit 88198ec1b0
30 files changed
+832 -557

No files matched your search

+2
View File
@@ -1377,6 +1377,8 @@
41c0c412lQ0NVVN9PsOSznQ-qhOiPA xen/include/asm-x86/vmx_vmcs.h
418fbcfe_WliJPToeVM-9VStvym-hw xen/include/asm-x86/x86_32/asm_defns.h
3e20b82fl1jmQiKdLy7fxMcutfpjWA xen/include/asm-x86/x86_32/domain_page.h
429c852fi3pvfa9kIjryYK5AGBmXAg xen/include/asm-x86/x86_32/page-2level.h
429c852fskvSOgcD5EC25_m9um9t4g xen/include/asm-x86/x86_32/page-3level.h
4208e2a3ZNFroNXbX9OYaOB-xtUyDQ xen/include/asm-x86/x86_32/page.h
3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/regs.h
3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h
+2 -2
View File
@@ -408,9 +408,9 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy)
for_each_exec_domain(d, ed)
{
if ( pagetable_val(ed->arch.guest_table) )
if ( pagetable_get_phys(ed->arch.guest_table) )
adjust(&frame_table[pagetable_get_pfn(ed->arch.guest_table)], 1);
if ( pagetable_val(ed->arch.shadow_table) )
if ( pagetable_get_phys(ed->arch.shadow_table) )
adjust(&frame_table[pagetable_get_pfn(ed->arch.shadow_table)], 0);
if ( ed->arch.monitor_shadow_ref )
adjust(&frame_table[ed->arch.monitor_shadow_ref], 0);
+43 -2
View File
@@ -101,6 +101,22 @@ __start:
xor %eax,%eax
rep stosb
#ifdef CONFIG_X86_PAE
/* Initialize low and high mappings of all memory with 2MB pages */
mov $idle_pg_table_l2-__PAGE_OFFSET,%edi
mov $0xe3,%eax /* PRESENT+RW+A+D+2MB */
1: mov %eax,__PAGE_OFFSET>>18(%edi) /* high mapping */
stosl /* low mapping */
add $4,%edi
add $(1<<L2_PAGETABLE_SHIFT),%eax
cmp $DIRECTMAP_PHYS_END+0xe3,%eax
jne 1b
1: stosl /* low mappings cover as much physmem as possible */
add $4,%edi
add $(1<<L2_PAGETABLE_SHIFT),%eax
cmp $__HYPERVISOR_VIRT_START+0xe3,%eax
jne 1b
#else
/* Initialize low and high mappings of all memory with 4MB pages */
mov $idle_pg_table-__PAGE_OFFSET,%edi
mov $0xe3,%eax /* PRESENT+RW+A+D+4MB */
@@ -113,6 +129,7 @@ __start:
add $(1<<L2_PAGETABLE_SHIFT),%eax
cmp $__HYPERVISOR_VIRT_START+0xe3,%eax
jne 1b
#endif
/* Initialise IDT with simple error defaults. */
lea ignore_int,%edx
@@ -204,10 +221,17 @@ ENTRY(gdt_table)
.quad 0x0000000000000000 /* unused */
.quad 0x00cf9a000000ffff /* 0xe008 ring 0 4.00GB code at 0x0 */
.quad 0x00cf92000000ffff /* 0xe010 ring 0 4.00GB data at 0x0 */
#ifdef CONFIG_X86_PAE
.quad 0x00cfba00000067ff
.quad 0x00cfb200000067ff
.quad 0x00cffa00000067ff
.quad 0x00cff200000067ff
#else
.quad 0x00cfba000000c3ff /* 0xe019 ring 1 3.95GB code at 0x0 */
.quad 0x00cfb2000000c3ff /* 0xe021 ring 1 3.95GB data at 0x0 */
.quad 0x00cffa000000c3ff /* 0xe02b ring 3 3.95GB code at 0x0 */
.quad 0x00cff2000000c3ff /* 0xe033 ring 3 3.95GB data at 0x0 */
#endif
.quad 0x0000000000000000 /* unused */
.fill 2*NR_CPUS,8,0 /* space for TSS and LDT per CPU */
@@ -215,10 +239,27 @@ ENTRY(gdt_table)
/* Maximum STACK_ORDER for x86/32 is 1. We must therefore ensure that the */
/* CPU0 stack is aligned on an even page boundary! */
ENTRY(cpu0_stack)
.org 0x2000 + STACK_SIZE
ENTRY(idle_pg_table)
#ifdef CONFIG_X86_PAE
ENTRY(idle_pg_table)
ENTRY(idle_pg_table_l3)
.quad 0x100000 + 0x2000 + STACK_SIZE + 1*PAGE_SIZE + 0x01
.quad 0x100000 + 0x2000 + STACK_SIZE + 2*PAGE_SIZE + 0x01
.quad 0x100000 + 0x2000 + STACK_SIZE + 3*PAGE_SIZE + 0x01
.quad 0x100000 + 0x2000 + STACK_SIZE + 4*PAGE_SIZE + 0x01
.org 0x2000 + STACK_SIZE + 1*PAGE_SIZE
ENTRY(idle_pg_table_l2)
.org 0x2000 + STACK_SIZE + 5*PAGE_SIZE
#else /* CONFIG_X86_PAE */
ENTRY(idle_pg_table)
ENTRY(idle_pg_table_l2) # Initial page directory is 4kB
.org 0x2000 + STACK_SIZE + PAGE_SIZE
#endif /* CONFIG_X86_PAE */
ENTRY(stext)
ENTRY(_stext)
+1 -1
View File
@@ -405,7 +405,7 @@ void arch_getdomaininfo_ctxt(
c->flags |= VGCF_VMX_GUEST;
#endif
c->pt_base = pagetable_val(ed->arch.guest_table);
c->pt_base = pagetable_get_phys(ed->arch.guest_table);
c->vm_assist = ed->domain->vm_assist;
}
+4 -4
View File
@@ -460,7 +460,7 @@ int arch_set_info_guest(
// trust the VMX domain builder. Xen should validate this
// page table, and/or build the table itself, or ???
//
if ( !pagetable_val(d->arch.phys_table) )
if ( !pagetable_get_phys(d->arch.phys_table) )
d->arch.phys_table = ed->arch.guest_table;
if ( (error = vmx_final_setup_guest(ed, c)) )
@@ -660,7 +660,7 @@ long do_switch_to_user(void)
struct exec_domain *ed = current;
if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) ||
unlikely(pagetable_val(ed->arch.guest_table_user) == 0) )
unlikely(pagetable_get_phys(ed->arch.guest_table_user) == 0) )
return -EFAULT;
toggle_guest_mode(ed);
@@ -978,7 +978,7 @@ void domain_relinquish_resources(struct domain *d)
/* Drop the in-use references to page-table bases. */
for_each_exec_domain ( d, ed )
{
if ( pagetable_val(ed->arch.guest_table) != 0 )
if ( pagetable_get_phys(ed->arch.guest_table) != 0 )
{
if ( shadow_mode_refcounts(d) )
put_page(&frame_table[pagetable_get_pfn(ed->arch.guest_table)]);
@@ -988,7 +988,7 @@ void domain_relinquish_resources(struct domain *d)
ed->arch.guest_table = mk_pagetable(0);
}
if ( pagetable_val(ed->arch.guest_table_user) != 0 )
if ( pagetable_get_phys(ed->arch.guest_table_user) != 0 )
{
if ( shadow_mode_refcounts(d) )
put_page(&frame_table[pagetable_get_pfn(ed->arch.guest_table_user)]);
+77 -15
View File
@@ -44,15 +44,15 @@ boolean_param("dom0_translate", opt_dom0_translate);
#if defined(__i386__)
/* No ring-3 access in initial leaf page tables. */
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#define L3_PROT (_PAGE_PRESENT)
#elif defined(__x86_64__)
/* Allow ring-3 access in long mode as guest cannot use ring 1. */
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
#endif
/* Don't change these: Linux expects just these bits to be set. */
/* (And that includes the bogus _PAGE_DIRTY!) */
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#endif
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
#define round_pgdown(_p) ((_p)&PAGE_MASK)
@@ -91,7 +91,11 @@ int construct_dom0(struct domain *d,
#elif defined(__x86_64__)
char *image_start = __va(_image_start);
char *initrd_start = __va(_initrd_start);
#endif
#if CONFIG_PAGING_LEVELS >= 4
l4_pgentry_t *l4tab = NULL, *l4start = NULL;
#endif
#if CONFIG_PAGING_LEVELS >= 3
l3_pgentry_t *l3tab = NULL, *l3start = NULL;
#endif
l2_pgentry_t *l2tab = NULL, *l2start = NULL;
@@ -143,7 +147,7 @@ int construct_dom0(struct domain *d,
panic("Not enough RAM for DOM0 reservation.\n");
alloc_start = page_to_phys(page);
alloc_end = alloc_start + (d->tot_pages << PAGE_SHIFT);
if ( (rc = parseelfimage(&dsi)) != 0 )
return rc;
@@ -172,10 +176,15 @@ int construct_dom0(struct domain *d,
v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
if ( (v_end - vstack_end) < (512UL << 10) )
v_end += 1UL << 22; /* Add extra 4MB to get >= 512kB padding. */
#if defined(__i386__)
#if defined(__i386__) && !defined(CONFIG_X86_PAE)
if ( (((v_end - dsi.v_start + ((1UL<<L2_PAGETABLE_SHIFT)-1)) >>
L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
break;
#elif defined(__i386__) && defined(CONFIG_X86_PAE)
/* 5 pages: 1x 3rd + 4x 2nd level */
if ( (((v_end - dsi.v_start + ((1UL<<L2_PAGETABLE_SHIFT)-1)) >>
L2_PAGETABLE_SHIFT) + 5) <= nr_pt_pages )
break;
#elif defined(__x86_64__)
#define NR(_l,_h,_s) \
(((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
@@ -249,6 +258,24 @@ int construct_dom0(struct domain *d,
}
/* WARNING: The new domain must have its 'processor' field filled in! */
#if CONFIG_PAGING_LEVELS == 3
l3start = l3tab = (l3_pgentry_t *)mpt_alloc; mpt_alloc += PAGE_SIZE;
l2start = l2tab = (l2_pgentry_t *)mpt_alloc; mpt_alloc += 4*PAGE_SIZE;
memcpy(l2tab, idle_pg_table_l2, 4*PAGE_SIZE);
for (i = 0; i < 4; i++) {
l3tab[i] = l3e_create_phys((u32)l2tab + i*PAGE_SIZE, L3_PROT);
l2tab[(LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT)+i] =
l2e_create_phys((u32)l2tab + i*PAGE_SIZE, __PAGE_HYPERVISOR);
}
unsigned long v;
for (v = PERDOMAIN_VIRT_START; v < PERDOMAIN_VIRT_END;
v += (1 << L2_PAGETABLE_SHIFT)) {
l2tab[v >> L2_PAGETABLE_SHIFT] =
l2e_create_phys(__pa(d->arch.mm_perdomain_pt) + (v-PERDOMAIN_VIRT_START),
__PAGE_HYPERVISOR);
}
ed->arch.guest_table = mk_pagetable((unsigned long)l3start);
#else
l2start = l2tab = (l2_pgentry_t *)mpt_alloc; mpt_alloc += PAGE_SIZE;
memcpy(l2tab, &idle_pg_table[0], PAGE_SIZE);
l2tab[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
@@ -256,8 +283,9 @@ int construct_dom0(struct domain *d,
l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
l2e_create_phys(__pa(d->arch.mm_perdomain_pt), __PAGE_HYPERVISOR);
ed->arch.guest_table = mk_pagetable((unsigned long)l2start);
#endif
l2tab += l2_table_offset(dsi.v_start);
l2tab += l2_linear_offset(dsi.v_start);
mfn = alloc_start >> PAGE_SHIFT;
for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ )
{
@@ -282,8 +310,8 @@ int construct_dom0(struct domain *d,
}
/* Pages that are part of page tables must be read only. */
l2tab = l2start + l2_table_offset(vpt_start);
l1start = l1tab = (l1_pgentry_t *)l2e_get_phys(*l2tab);
l2tab = l2start + l2_linear_offset(vpt_start);
l1start = l1tab = (l1_pgentry_t *)(u32)l2e_get_phys(*l2tab);
l1tab += l1_table_offset(vpt_start);
for ( count = 0; count < nr_pt_pages; count++ )
{
@@ -294,6 +322,34 @@ int construct_dom0(struct domain *d,
if ( !get_page_type(page, PGT_writable_page) )
BUG();
#if CONFIG_PAGING_LEVELS == 3
switch (count) {
case 0:
page->u.inuse.type_info &= ~PGT_type_mask;
page->u.inuse.type_info |= PGT_l3_page_table;
get_page(page, d); /* an extra ref because of readable mapping */
/* Get another ref to L3 page so that it can be pinned. */
if ( !get_page_and_type(page, d, PGT_l3_page_table) )
BUG();
set_bit(_PGT_pinned, &page->u.inuse.type_info);
break;
case 1 ... 4:
page->u.inuse.type_info &= ~PGT_type_mask;
page->u.inuse.type_info |= PGT_l2_page_table;
page->u.inuse.type_info |=
(count-1) << PGT_va_shift;
get_page(page, d); /* an extra ref because of readable mapping */
break;
default:
page->u.inuse.type_info &= ~PGT_type_mask;
page->u.inuse.type_info |= PGT_l1_page_table;
page->u.inuse.type_info |=
((dsi.v_start>>L2_PAGETABLE_SHIFT)+(count-5))<<PGT_va_shift;
get_page(page, d); /* an extra ref because of readable mapping */
break;
}
#else
if ( count == 0 )
{
page->u.inuse.type_info &= ~PGT_type_mask;
@@ -326,8 +382,9 @@ int construct_dom0(struct domain *d,
*/
get_page(page, d); /* an extra ref because of readable mapping */
}
#endif
if ( !((unsigned long)++l1tab & (PAGE_SIZE - 1)) )
l1start = l1tab = (l1_pgentry_t *)l2e_get_phys(*++l2tab);
l1start = l1tab = (l1_pgentry_t *)(u32)l2e_get_phys(*++l2tab);
}
#elif defined(__x86_64__)
@@ -538,10 +595,8 @@ int construct_dom0(struct domain *d,
#if defined(__i386__)
/* Destroy low mappings - they were only for our convenience. */
for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
if ( l2e_get_flags(l2start[i]) & _PAGE_PSE )
l2start[i] = l2e_empty();
zap_low_mappings(); /* Do the same for the idle page tables. */
zap_low_mappings(l2start);
zap_low_mappings(idle_pg_table_l2);
#endif
/* DOM0 gets access to everything. */
@@ -558,6 +613,12 @@ int construct_dom0(struct domain *d,
: SHM_enable));
if ( opt_dom0_translate )
{
#if defined(__i386__) && defined(CONFIG_X86_PAE)
printk("FIXME: PAE code needed here: %s:%d (%s)\n",
__FILE__, __LINE__, __FUNCTION__);
for ( ; ; )
__asm__ __volatile__ ( "hlt" );
#else
/* Hmm, what does this?
Looks like isn't portable across 32/64 bit and pae/non-pae ...
-- kraxel */
@@ -573,13 +634,14 @@ int construct_dom0(struct domain *d,
// so that we can easily access it.
//
ASSERT( root_get_value(idle_pg_table[1]) == 0 );
ASSERT( pagetable_val(d->arch.phys_table) );
ASSERT( pagetable_get_phys(d->arch.phys_table) );
idle_pg_table[1] = root_create_phys(
pagetable_val(d->arch.phys_table), __PAGE_HYPERVISOR);
pagetable_get_phys(d->arch.phys_table), __PAGE_HYPERVISOR);
translate_l2pgtable(d, (l1_pgentry_t *)(1u << L2_PAGETABLE_SHIFT),
pagetable_get_pfn(ed->arch.guest_table));
idle_pg_table[1] = root_empty();
local_flush_tlb();
#endif
}
update_pagetables(ed); /* XXX SMP */
+1 -2
View File
@@ -11,8 +11,7 @@ struct domain idle0_domain = {
struct exec_domain idle0_exec_domain = {
processor: 0,
domain: &idle0_domain,
arch: IDLE0_ARCH_EXEC_DOMAIN
domain: &idle0_domain
};
struct tss_struct init_tss[NR_CPUS];
+239 -109
View File
@@ -121,7 +121,8 @@
static void free_l2_table(struct pfn_info *page);
static void free_l1_table(struct pfn_info *page);
static int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long);
static int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long,
unsigned int type);
static int mod_l1_entry(l1_pgentry_t *, l1_pgentry_t);
/* Used to defer flushing of memory structures. */
@@ -149,21 +150,22 @@ unsigned long max_page;
void __init init_frametable(void)
{
unsigned long i, p;
unsigned long i, p, step;
frame_table = (struct pfn_info *)FRAMETABLE_VIRT_START;
frame_table_size = max_page * sizeof(struct pfn_info);
frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK;
for ( i = 0; i < frame_table_size; i += (4UL << 20) )
step = (1 << L2_PAGETABLE_SHIFT);
for ( i = 0; i < frame_table_size; i += step )
{
p = alloc_boot_pages(min(frame_table_size - i, 4UL << 20), 4UL << 20);
p = alloc_boot_pages(min(frame_table_size - i, step), step);
if ( p == 0 )
panic("Not enough memory for frame table\n");
map_pages_to_xen(
FRAMETABLE_VIRT_START + i,
p >> PAGE_SHIFT,
4UL << (20-PAGE_SHIFT),
step >> PAGE_SHIFT,
PAGE_HYPERVISOR);
}
@@ -232,7 +234,7 @@ void arch_init_memory(void)
void write_ptbase(struct exec_domain *ed)
{
write_cr3(pagetable_val(ed->arch.monitor_table));
write_cr3(pagetable_get_phys(ed->arch.monitor_table));
}
void invalidate_shadow_ldt(struct exec_domain *d)
@@ -375,7 +377,6 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr,
return 1;
}
/*
* We allow root tables to map each other (a.k.a. linear page tables). It
* needs some special care with reference counts and access permissions:
@@ -432,7 +433,6 @@ get_linear_pagetable(
return 1;
}
int
get_page_from_l1e(
l1_pgentry_t l1e, struct domain *d)
@@ -446,8 +446,7 @@ get_page_from_l1e(
if ( unlikely(l1e_get_flags(l1e) & L1_DISALLOW_MASK) )
{
MEM_LOG("Bad L1 type settings %lx %lx", l1e_get_value(l1e),
l1e_get_value(l1e) & L1_DISALLOW_MASK);
MEM_LOG("Bad L1 flags %x\n", l1e_get_flags(l1e) & L1_DISALLOW_MASK);
return 0;
}
@@ -482,7 +481,7 @@ get_page_from_l1e(
static int
get_page_from_l2e(
l2_pgentry_t l2e, unsigned long pfn,
struct domain *d, unsigned long va_idx)
struct domain *d, unsigned long vaddr)
{
int rc;
@@ -493,45 +492,58 @@ get_page_from_l2e(
if ( unlikely((l2e_get_flags(l2e) & L2_DISALLOW_MASK)) )
{
MEM_LOG("Bad L2 page type settings %lx",
l2e_get_value(l2e) & L2_DISALLOW_MASK);
MEM_LOG("Bad L2 flags %x\n", l2e_get_flags(l2e) & L2_DISALLOW_MASK);
return 0;
}
vaddr >>= L2_PAGETABLE_SHIFT;
vaddr <<= PGT_va_shift;
rc = get_page_and_type_from_pagenr(
l2e_get_pfn(l2e),
PGT_l1_page_table | (va_idx<<PGT_va_shift), d);
l2e_get_pfn(l2e), PGT_l1_page_table | vaddr, d);
#if defined(__i386__)
return rc ? rc : get_linear_pagetable(l2e, pfn, d);
#elif defined(__x86_64__)
return rc;
#if CONFIG_PAGING_LEVELS == 2
if (!rc)
rc = get_linear_pagetable(l2e, pfn, d);
#endif
return rc;
}
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
static int
get_page_from_l3e(
l3_pgentry_t l3e, unsigned long pfn, struct domain *d)
l3_pgentry_t l3e, unsigned long pfn,
struct domain *d, unsigned long vaddr)
{
ASSERT( !shadow_mode_refcounts(d) );
int rc;
if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
return 1;
if ( unlikely((l3e_get_flags(l3e) & L3_DISALLOW_MASK)) )
{
MEM_LOG("Bad L3 page type settings %lx",
l3e_get_value(l3e) & L3_DISALLOW_MASK);
MEM_LOG("Bad L3 flags %x\n", l3e_get_flags(l3e) & L3_DISALLOW_MASK);
return 0;
}
return get_page_and_type_from_pagenr(
l3e_get_pfn(l3e), PGT_l2_page_table, d);
vaddr >>= L3_PAGETABLE_SHIFT;
vaddr <<= PGT_va_shift;
rc = get_page_and_type_from_pagenr(
l3e_get_pfn(l3e),
PGT_l2_page_table | vaddr, d);
#if CONFIG_PAGING_LEVELS == 3
if (!rc)
rc = get_linear_pagetable(l3e, pfn, d);
#endif
return rc;
}
#endif /* 3 level */
#if CONFIG_PAGING_LEVELS >= 4
static int
get_page_from_l4e(
@@ -546,8 +558,7 @@ get_page_from_l4e(
if ( unlikely((l4e_get_flags(l4e) & L4_DISALLOW_MASK)) )
{
MEM_LOG("Bad L4 page type settings %lx",
l4e_get_value(l4e) & L4_DISALLOW_MASK);
MEM_LOG("Bad L4 flags %x\n", l4e_get_flags(l4e) & L4_DISALLOW_MASK);
return 0;
}
@@ -560,7 +571,7 @@ get_page_from_l4e(
return 1;
}
#endif /* __x86_64__ */
#endif /* 4 level */
void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
@@ -622,7 +633,7 @@ static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
}
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn)
{
@@ -631,6 +642,9 @@ static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn)
put_page_and_type(&frame_table[l3e_get_pfn(l3e)]);
}
#endif
#if CONFIG_PAGING_LEVELS >= 4
static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn)
{
@@ -639,7 +653,7 @@ static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn)
put_page_and_type(&frame_table[l4e_get_pfn(l4e)]);
}
#endif /* __x86_64__ */
#endif
static int alloc_l1_table(struct pfn_info *page)
@@ -670,11 +684,61 @@ static int alloc_l1_table(struct pfn_info *page)
return 0;
}
#ifdef CONFIG_X86_PAE
static inline int fixup_pae_linear_mappings(l3_pgentry_t *pl3e)
{
l2_pgentry_t *pl2e;
unsigned long vaddr;
int i,idx;
static int alloc_l2_table(struct pfn_info *page)
while ((unsigned long)pl3e & ~PAGE_MASK)
pl3e--;
if (!(l3e_get_flags(pl3e[3]) & _PAGE_PRESENT)) {
printk("Installing a L3 PAE pt without L2 in slot #3 isn't going to fly ...\n");
return 0;
}
pl2e = map_domain_mem(l3e_get_phys(pl3e[3]));
for (i = 0; i < 4; i++) {
vaddr = LINEAR_PT_VIRT_START + (i << L2_PAGETABLE_SHIFT);
idx = (vaddr >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES-1);
if (l3e_get_flags(pl3e[i]) & _PAGE_PRESENT) {
pl2e[idx] = l2e_create_phys(l3e_get_phys(pl3e[i]),
__PAGE_HYPERVISOR);
} else
pl2e[idx] = l2e_empty();
}
unmap_domain_mem(pl2e);
return 1;
}
static inline unsigned long fixup_pae_vaddr(unsigned long l2vaddr,
unsigned long l2type)
{
unsigned long l3vaddr;
if ((l2type & PGT_va_mask) == PGT_va_unknown) {
printk("%s: hooking one l2 pt into multiple l3 slots isn't allowed, sorry\n",
__FUNCTION__);
domain_crash();
}
l3vaddr = ((l2type & PGT_va_mask) >> PGT_va_shift)
<< L3_PAGETABLE_SHIFT;
return l3vaddr + l2vaddr;
}
#else
# define fixup_pae_linear_mappings(unused) (1)
# define fixup_pae_vaddr(vaddr, type) (vaddr)
#endif
static int alloc_l2_table(struct pfn_info *page, unsigned int type)
{
struct domain *d = page_get_owner(page);
unsigned long pfn = page_to_pfn(page);
unsigned long vaddr;
l2_pgentry_t *pl2e;
int i;
@@ -682,21 +746,24 @@ static int alloc_l2_table(struct pfn_info *page)
if ( (PGT_base_page_table == PGT_l2_page_table) &&
unlikely(shadow_mode_refcounts(d)) )
return 1;
ASSERT( !shadow_mode_refcounts(d) );
pl2e = map_domain_mem(pfn << PAGE_SHIFT);
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
if ( is_guest_l2_slot(i) &&
unlikely(!get_page_from_l2e(pl2e[i], pfn, d, i)) )
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) {
vaddr = i << L2_PAGETABLE_SHIFT;
vaddr = fixup_pae_vaddr(vaddr,type);
if ( is_guest_l2_slot(type, i) &&
unlikely(!get_page_from_l2e(pl2e[i], pfn, d, vaddr)) )
goto fail;
}
#if defined(__i386__)
#if CONFIG_PAGING_LEVELS == 2
/* Xen private mappings. */
memcpy(&pl2e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
&idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],
ROOT_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
memcpy(&pl2e[L2_PAGETABLE_FIRST_XEN_SLOT],
&idle_pg_table[L2_PAGETABLE_FIRST_XEN_SLOT],
L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
pl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =
l2e_create_pfn(pfn, __PAGE_HYPERVISOR);
pl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
@@ -704,13 +771,31 @@ static int alloc_l2_table(struct pfn_info *page)
virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt),
__PAGE_HYPERVISOR);
#endif
#if CONFIG_PAGING_LEVELS == 3
if (3 == ((type & PGT_va_mask) >> PGT_va_shift)) {
unsigned long v,src,dst;
void *virt;
/* Xen private mappings. */
dst = L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1);
src = L2_PAGETABLE_FIRST_XEN_SLOT;
memcpy(&pl2e[dst], &idle_pg_table_l2[src],
L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
for (v = PERDOMAIN_VIRT_START; v < PERDOMAIN_VIRT_END;
v += (1 << L2_PAGETABLE_SHIFT)) {
dst = (v >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES-1);
virt = page_get_owner(page)->arch.mm_perdomain_pt + (v-PERDOMAIN_VIRT_START);
pl2e[dst] = l2e_create_page(virt_to_page(virt), __PAGE_HYPERVISOR);
}
/* see fixup_pae_linear_mappings() for linear pagetables */
}
#endif
unmap_domain_mem(pl2e);
return 1;
fail:
while ( i-- > 0 )
if ( is_guest_l2_slot(i) )
if ( is_guest_l2_slot(type, i) )
put_page_from_l2e(pl2e[i], pfn);
unmap_domain_mem(pl2e);
@@ -718,22 +803,29 @@ static int alloc_l2_table(struct pfn_info *page)
}
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
static int alloc_l3_table(struct pfn_info *page)
{
struct domain *d = page_get_owner(page);
unsigned long pfn = page_to_pfn(page);
l3_pgentry_t *pl3e = page_to_virt(page);
unsigned long vaddr;
l3_pgentry_t *pl3e;
int i;
ASSERT( !shadow_mode_refcounts(d) );
for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
pl3e = map_domain_mem(pfn << PAGE_SHIFT);
for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) {
vaddr = i << L3_PAGETABLE_SHIFT;
if ( is_guest_l3_slot(i) &&
unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) )
unlikely(!get_page_from_l3e(pl3e[i], pfn, d, vaddr)) )
goto fail;
}
if (!fixup_pae_linear_mappings(pl3e))
goto fail;
unmap_domain_mem(pl3e);
return 1;
fail:
@@ -741,9 +833,13 @@ static int alloc_l3_table(struct pfn_info *page)
if ( is_guest_l3_slot(i) )
put_page_from_l3e(pl3e[i], pfn);
unmap_domain_mem(pl3e);
return 0;
}
#endif
#if CONFIG_PAGING_LEVELS >= 4
static int alloc_l4_table(struct pfn_info *page)
{
@@ -813,27 +909,35 @@ static void free_l2_table(struct pfn_info *page)
pl2e = map_domain_mem(pfn << PAGE_SHIFT);
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
if ( is_guest_l2_slot(i) )
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) {
if ( is_guest_l2_slot(page->u.inuse.type_info, i) )
put_page_from_l2e(pl2e[i], pfn);
}
unmap_domain_mem(pl2e);
}
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
static void free_l3_table(struct pfn_info *page)
{
unsigned long pfn = page_to_pfn(page);
l3_pgentry_t *pl3e = page_to_virt(page);
l3_pgentry_t *pl3e;
int i;
pl3e = map_domain_mem(pfn << PAGE_SHIFT);
for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
if ( is_guest_l3_slot(i) )
put_page_from_l3e(pl3e[i], pfn);
unmap_domain_mem(pl3e);
}
#endif
#if CONFIG_PAGING_LEVELS >= 4
static void free_l4_table(struct pfn_info *page)
{
@@ -846,25 +950,24 @@ static void free_l4_table(struct pfn_info *page)
put_page_from_l4e(pl4e[i], pfn);
}
#endif /* __x86_64__ */
#endif
static inline int update_l1e(l1_pgentry_t *pl1e,
l1_pgentry_t ol1e,
l1_pgentry_t nl1e)
{
/* FIXME: breaks with PAE */
unsigned long o = l1e_get_value(ol1e);
unsigned long n = l1e_get_value(nl1e);
intpte_t o = l1e_get_value(ol1e);
intpte_t n = l1e_get_value(nl1e);
if ( unlikely(cmpxchg_user(pl1e, o, n) != 0) ||
unlikely(o != l1e_get_value(ol1e)) )
{
MEM_LOG("Failed to update %lx -> %lx: saw %lx",
l1e_get_value(ol1e), l1e_get_value(nl1e), o);
MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte ": saw %" PRIpte "\n",
l1e_get_value(ol1e),
l1e_get_value(nl1e),
o);
return 0;
}
return 1;
}
@@ -885,8 +988,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e)
{
if ( unlikely(l1e_get_flags(nl1e) & L1_DISALLOW_MASK) )
{
MEM_LOG("Bad L1 type settings %lx",
l1e_get_value(nl1e) & L1_DISALLOW_MASK);
MEM_LOG("Bad L1 type settings %" PRIpte "\n",
(l1e_get_value(nl1e) & L1_DISALLOW_MASK));
return 0;
}
@@ -913,25 +1016,27 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e)
return 1;
}
#define UPDATE_ENTRY(_t,_p,_o,_n) ({ \
unsigned long __o = cmpxchg((unsigned long *)(_p), \
_t ## e_get_value(_o), \
_t ## e_get_value(_n)); \
intpte_t __o = cmpxchg((intpte_t *)(_p), \
_t ## e_get_value(_o), \
_t ## e_get_value(_n)); \
if ( __o != _t ## e_get_value(_o) ) \
MEM_LOG("Failed to update %lx -> %lx: saw %lx", \
_t ## e_get_value(_o), _t ## e_get_value(_n), __o); \
MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte ": saw %" PRIpte "", \
(_t ## e_get_value(_o)), \
(_t ## e_get_value(_n)), \
(__o)); \
(__o == _t ## e_get_value(_o)); })
/* Update the L2 entry at pl2e to new value nl2e. pl2e is within frame pfn. */
static int mod_l2_entry(l2_pgentry_t *pl2e,
l2_pgentry_t nl2e,
unsigned long pfn)
unsigned long pfn,
unsigned int type)
{
l2_pgentry_t ol2e;
unsigned long vaddr;
if ( unlikely(!is_guest_l2_slot(pgentry_ptr_to_slot(pl2e))) )
if ( unlikely(!is_guest_l2_slot(type,pgentry_ptr_to_slot(pl2e))) )
{
MEM_LOG("Illegal L2 update attempt in Xen-private area %p", pl2e);
return 0;
@@ -944,8 +1049,8 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
{
if ( unlikely(l2e_get_flags(nl2e) & L2_DISALLOW_MASK) )
{
MEM_LOG("Bad L2 type settings %lx",
l2e_get_value(nl2e) & L2_DISALLOW_MASK);
MEM_LOG("Bad L2 type settings %" PRIpte "\n",
(l2e_get_value(nl2e) & L2_DISALLOW_MASK));
return 0;
}
@@ -953,9 +1058,10 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
if ( !l2e_has_changed(&ol2e, &nl2e, _PAGE_PRESENT))
return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e);
if ( unlikely(!get_page_from_l2e(nl2e, pfn, current->domain,
((unsigned long)pl2e &
~PAGE_MASK) >> 2)) )
vaddr = (((unsigned long)pl2e & ~PAGE_MASK) / sizeof(l2_pgentry_t))
<< L2_PAGETABLE_SHIFT;
vaddr = fixup_pae_vaddr(vaddr,type);
if ( unlikely(!get_page_from_l2e(nl2e, pfn, current->domain, vaddr)) )
return 0;
if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e)) )
@@ -975,7 +1081,7 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
}
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
/* Update the L3 entry at pl3e to new value nl3e. pl3e is within frame pfn. */
static int mod_l3_entry(l3_pgentry_t *pl3e,
@@ -983,6 +1089,7 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
unsigned long pfn)
{
l3_pgentry_t ol3e;
unsigned long vaddr;
if ( unlikely(!is_guest_l3_slot(pgentry_ptr_to_slot(pl3e))) )
{
@@ -997,8 +1104,8 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
{
if ( unlikely(l3e_get_flags(nl3e) & L3_DISALLOW_MASK) )
{
MEM_LOG("Bad L3 type settings %lx",
l3e_get_value(nl3e) & L3_DISALLOW_MASK);
MEM_LOG("Bad L3 type settings %" PRIpte "",
(u64)(l3e_get_value(nl3e) & L3_DISALLOW_MASK));
return 0;
}
@@ -1006,26 +1113,33 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
if (!l3e_has_changed(&ol3e, &nl3e, _PAGE_PRESENT))
return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e);
if ( unlikely(!get_page_from_l3e(nl3e, pfn, current->domain)) )
vaddr = (((unsigned long)pl3e & ~PAGE_MASK) / sizeof(l3_pgentry_t))
<< L3_PAGETABLE_SHIFT;
if ( unlikely(!get_page_from_l3e(nl3e, pfn, current->domain, vaddr)) )
return 0;
if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) )
if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e) ||
!fixup_pae_linear_mappings(pl3e)) )
{
put_page_from_l3e(nl3e, pfn);
return 0;
}
put_page_from_l3e(ol3e, pfn);
return 1;
}
if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) )
if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e) ||
!fixup_pae_linear_mappings(pl3e)) )
return 0;
put_page_from_l3e(ol3e, pfn);
return 1;
}
#endif
#if CONFIG_PAGING_LEVELS >= 4
/* Update the L4 entry at pl4e to new value nl4e. pl4e is within frame pfn. */
static int mod_l4_entry(l4_pgentry_t *pl4e,
@@ -1076,20 +1190,21 @@ static int mod_l4_entry(l4_pgentry_t *pl4e,
return 1;
}
#endif /* __x86_64__ */
#endif
int alloc_page_type(struct pfn_info *page, unsigned int type)
{
switch ( type )
switch ( type & PGT_type_mask )
{
case PGT_l1_page_table:
return alloc_l1_table(page);
case PGT_l2_page_table:
return alloc_l2_table(page);
#ifdef __x86_64__
return alloc_l2_table(page, type);
#if CONFIG_PAGING_LEVELS >= 3
case PGT_l3_page_table:
return alloc_l3_table(page);
#endif
#if CONFIG_PAGING_LEVELS >= 4
case PGT_l4_page_table:
return alloc_l4_table(page);
#endif
@@ -1124,7 +1239,7 @@ void free_page_type(struct pfn_info *page, unsigned int type)
}
}
switch ( type )
switch (type & PGT_type_mask)
{
case PGT_l1_page_table:
free_l1_table(page);
@@ -1134,17 +1249,21 @@ void free_page_type(struct pfn_info *page, unsigned int type)
free_l2_table(page);
break;
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
case PGT_l3_page_table:
free_l3_table(page);
break;
#endif
#if CONFIG_PAGING_LEVELS >= 4
case PGT_l4_page_table:
free_l4_table(page);
break;
#endif
default:
printk("%s: type %x pfn %lx\n",__FUNCTION__,
type, page_to_pfn(page));
BUG();
}
}
@@ -1187,7 +1306,7 @@ void put_page_type(struct pfn_info *page)
x & ~PGT_validated)) != x) )
goto again;
/* We cleared the 'valid bit' so we do the clean up. */
free_page_type(page, x & PGT_type_mask);
free_page_type(page, x);
/* Carry on, but with the 'valid bit' now clear. */
x &= ~PGT_validated;
nx &= ~PGT_validated;
@@ -1270,6 +1389,10 @@ int get_page_type(struct pfn_info *page, u32 type)
/* This table is may be mapped at multiple locations. */
nx &= ~PGT_va_mask;
nx |= PGT_va_unknown;
#if 0 /* debug */
printk("%s: pfn %lx type %x -> %x (tag as unknown)\n",
__FUNCTION__,page_to_pfn(page),x,nx);
#endif
}
}
if ( unlikely(!(x & PGT_validated)) )
@@ -1286,7 +1409,7 @@ int get_page_type(struct pfn_info *page, u32 type)
if ( unlikely(!(nx & PGT_validated)) )
{
/* Try to validate page type; drop the new reference on failure. */
if ( unlikely(!alloc_page_type(page, type & PGT_type_mask)) )
if ( unlikely(!alloc_page_type(page, type)) )
{
MEM_LOG("Error while validating pfn %lx for type %08x."
" caf=%08x taf=%08x",
@@ -1537,15 +1660,17 @@ int do_mmuext_op(
type = PGT_l2_page_table;
goto pin_page;
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
case MMUEXT_PIN_L3_TABLE:
type = PGT_l3_page_table;
goto pin_page;
#endif
#if CONFIG_PAGING_LEVELS >= 4
case MMUEXT_PIN_L4_TABLE:
type = PGT_l4_page_table;
goto pin_page;
#endif /* __x86_64__ */
#endif
case MMUEXT_UNPIN_TABLE:
if ( unlikely(!(okay = get_page_from_pagenr(op.mfn, FOREIGNDOM))) )
@@ -1912,19 +2037,20 @@ int do_mmu_update(
break;
case PGT_l2_page_table:
ASSERT( !shadow_mode_refcounts(d) );
if ( likely(get_page_type(page, PGT_l2_page_table)) )
if ( likely(get_page_type(
page, type_info & (PGT_type_mask|PGT_va_mask))) )
{
l2_pgentry_t l2e;
/* FIXME: doesn't work with PAE */
l2e = l2e_create_phys(req.val, req.val);
okay = mod_l2_entry(va, l2e, mfn);
okay = mod_l2_entry((l2_pgentry_t *)va, l2e, mfn, type_info);
if ( okay && unlikely(shadow_mode_enabled(d)) )
shadow_l2_normal_pt_update(d, req.ptr, l2e, &sh_mapcache);
put_page_type(page);
}
break;
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
case PGT_l3_page_table:
ASSERT( !shadow_mode_refcounts(d) );
if ( likely(get_page_type(page, PGT_l3_page_table)) )
@@ -1939,6 +2065,8 @@ int do_mmu_update(
put_page_type(page);
}
break;
#endif
#if CONFIG_PAGING_LEVELS >= 4
case PGT_l4_page_table:
ASSERT( !shadow_mode_refcounts(d) );
if ( likely(get_page_type(page, PGT_l4_page_table)) )
@@ -1952,7 +2080,7 @@ int do_mmu_update(
put_page_type(page);
}
break;
#endif /* __x86_64__ */
#endif
default:
if ( likely(get_page_type(page, PGT_writable_page)) )
{
@@ -2119,9 +2247,10 @@ int update_grant_va_mapping(unsigned long va,
int do_update_va_mapping(unsigned long va,
l1_pgentry_t val,
unsigned long val32,
unsigned long flags)
{
l1_pgentry_t val = l1e_create_phys(val32,val32);
struct exec_domain *ed = current;
struct domain *d = ed->domain;
unsigned int cpu = ed->processor;
@@ -2216,7 +2345,7 @@ int do_update_va_mapping(unsigned long va,
}
int do_update_va_mapping_otherdomain(unsigned long va,
l1_pgentry_t val,
unsigned long val32,
unsigned long flags,
domid_t domid)
{
@@ -2234,7 +2363,7 @@ int do_update_va_mapping_otherdomain(unsigned long va,
return -ESRCH;
}
rc = do_update_va_mapping(va, val, flags);
rc = do_update_va_mapping(va, val32, flags);
return rc;
}
@@ -2551,8 +2680,8 @@ void ptwr_flush(struct domain *d, const int which)
static int ptwr_emulated_update(
unsigned long addr,
unsigned long old,
unsigned long val,
physaddr_t old,
physaddr_t val,
unsigned int bytes,
unsigned int do_cmpxchg)
{
@@ -2570,21 +2699,22 @@ static int ptwr_emulated_update(
}
/* Turn a sub-word access into a full-word access. */
/* FIXME: needs tweaks for PAE */
if ( (addr & ((BITS_PER_LONG/8)-1)) != 0 )
if (bytes != sizeof(physaddr_t))
{
int rc;
unsigned long full;
unsigned int mask = addr & ((BITS_PER_LONG/8)-1);
physaddr_t full;
unsigned int offset = addr & (sizeof(physaddr_t)-1);
/* Align address; read full word. */
addr &= ~((BITS_PER_LONG/8)-1);
if ( (rc = x86_emulate_read_std(addr, &full, BITS_PER_LONG/8)) )
return rc;
addr &= ~(sizeof(physaddr_t)-1);
if ( (rc = x86_emulate_read_std(addr, (unsigned long *)&full,
sizeof(physaddr_t))) )
return rc;
/* Mask out bits provided by caller. */
full &= ~((1UL << (bytes*8)) - 1UL) << (mask*8);
full &= ~((((physaddr_t)1 << (bytes*8)) - 1) << (offset*8));
/* Shift the caller value and OR in the missing bits. */
val &= (1UL << (bytes*8)) - 1UL;
val <<= mask*8;
val &= (((physaddr_t)1 << (bytes*8)) - 1);
val <<= (offset)*8;
val |= full;
}
+1 -1
View File
@@ -87,7 +87,7 @@ extern unsigned long cpu0_stack[];
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
#if defined(CONFIG_X86_64)
#if CONFIG_PAGING_LEVELS > 2
unsigned long mmu_cr4_features = X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE;
#else
unsigned long mmu_cr4_features = X86_CR4_PSE | X86_CR4_PGE;
+30 -21
View File
@@ -358,13 +358,13 @@ free_shadow_hl2_table(struct domain *d, unsigned long smfn)
}
static void inline
free_shadow_l2_table(struct domain *d, unsigned long smfn)
free_shadow_l2_table(struct domain *d, unsigned long smfn, unsigned int type)
{
l2_pgentry_t *pl2e = map_domain_mem(smfn << PAGE_SHIFT);
int i, external = shadow_mode_external(d);
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
if ( external || is_guest_l2_slot(i) )
if ( external || is_guest_l2_slot(type, i) )
if ( l2e_get_flags(pl2e[i]) & _PAGE_PRESENT )
put_shadow_ref(l2e_get_pfn(pl2e[i]));
@@ -404,7 +404,7 @@ void free_shadow_page(unsigned long smfn)
case PGT_l2_shadow:
perfc_decr(shadow_l2_pages);
shadow_demote(d, gpfn, gmfn);
free_shadow_l2_table(d, smfn);
free_shadow_l2_table(d, smfn, page->u.inuse.type_info);
break;
case PGT_hl2_shadow:
@@ -573,7 +573,7 @@ static void free_shadow_pages(struct domain *d)
//
for_each_exec_domain(d, ed)
{
if ( pagetable_val(ed->arch.shadow_table) )
if ( pagetable_get_phys(ed->arch.shadow_table) )
{
put_shadow_ref(pagetable_get_pfn(ed->arch.shadow_table));
ed->arch.shadow_table = mk_pagetable(0);
@@ -684,7 +684,7 @@ static void alloc_monitor_pagetable(struct exec_domain *ed)
struct pfn_info *mmfn_info;
struct domain *d = ed->domain;
ASSERT(pagetable_val(ed->arch.monitor_table) == 0);
ASSERT(pagetable_get_phys(ed->arch.monitor_table) == 0);
mmfn_info = alloc_domheap_page(NULL);
ASSERT(mmfn_info != NULL);
@@ -705,7 +705,7 @@ static void alloc_monitor_pagetable(struct exec_domain *ed)
// map the phys_to_machine map into the Read-Only MPT space for this domain
mpl2e[l2_table_offset(RO_MPT_VIRT_START)] =
l2e_create_phys(pagetable_val(d->arch.phys_table),
l2e_create_phys(pagetable_get_phys(d->arch.phys_table),
__PAGE_HYPERVISOR);
// Don't (yet) have mappings for these...
@@ -726,7 +726,7 @@ void free_monitor_pagetable(struct exec_domain *ed)
l2_pgentry_t *mpl2e, hl2e, sl2e;
unsigned long mfn;
ASSERT( pagetable_val(ed->arch.monitor_table) );
ASSERT( pagetable_get_phys(ed->arch.monitor_table) );
mpl2e = ed->arch.monitor_vtable;
@@ -766,7 +766,7 @@ set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
struct map_dom_mem_cache *l2cache,
struct map_dom_mem_cache *l1cache)
{
unsigned long phystab = pagetable_val(d->arch.phys_table);
unsigned long phystab = pagetable_get_phys(d->arch.phys_table);
l2_pgentry_t *l2, l2e;
l1_pgentry_t *l1;
struct pfn_info *l1page;
@@ -965,7 +965,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode)
{
if ( !(new_modes & SHM_external) )
{
ASSERT( !pagetable_val(d->arch.phys_table) );
ASSERT( !pagetable_get_phys(d->arch.phys_table) );
if ( !alloc_p2m_table(d) )
{
printk("alloc_p2m_table failed (out-of-memory?)\n");
@@ -1051,7 +1051,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode)
d->arch.shadow_dirty_bitmap = NULL;
}
if ( (new_modes & SHM_translate) && !(new_modes & SHM_external) &&
pagetable_val(d->arch.phys_table) )
pagetable_get_phys(d->arch.phys_table) )
{
free_p2m_table(d);
}
@@ -1093,7 +1093,8 @@ translate_l1pgtable(struct domain *d, l1_pgentry_t *p2m, unsigned long l1mfn)
// up dom0.
//
void
translate_l2pgtable(struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn)
translate_l2pgtable(struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn,
unsigned int type)
{
int i;
l2_pgentry_t *l2;
@@ -1103,7 +1104,7 @@ translate_l2pgtable(struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn)
l2 = map_domain_mem(l2mfn << PAGE_SHIFT);
for (i = 0; i < L2_PAGETABLE_ENTRIES; i++)
{
if ( is_guest_l2_slot(i) &&
if ( is_guest_l2_slot(type, i) &&
(l2e_get_flags(l2[i]) & _PAGE_PRESENT) )
{
unsigned long mfn = l2e_get_pfn(l2[i]);
@@ -1403,13 +1404,13 @@ gpfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
perfc_incrc(gpfn_to_mfn_foreign);
unsigned long va = gpfn << PAGE_SHIFT;
unsigned long phystab = pagetable_val(d->arch.phys_table);
unsigned long phystab = pagetable_get_phys(d->arch.phys_table);
l2_pgentry_t *l2 = map_domain_mem(phystab);
l2_pgentry_t l2e = l2[l2_table_offset(va)];
unmap_domain_mem(l2);
if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
{
printk("gpfn_to_mfn_foreign(d->id=%d, gpfn=%lx) => 0 l2e=%lx\n",
printk("gpfn_to_mfn_foreign(d->id=%d, gpfn=%lx) => 0 l2e=%" PRIpte "\n",
d->domain_id, gpfn, l2e_get_value(l2e));
return INVALID_MFN;
}
@@ -1425,7 +1426,7 @@ gpfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
{
printk("gpfn_to_mfn_foreign(d->id=%d, gpfn=%lx) => 0 l1e=%lx\n",
printk("gpfn_to_mfn_foreign(d->id=%d, gpfn=%lx) => 0 l1e=%" PRIpte "\n",
d->domain_id, gpfn, l1e_get_value(l1e));
return INVALID_MFN;
}
@@ -1540,7 +1541,7 @@ static unsigned long shadow_l2_table(
unsigned long hl2mfn;
spl2e[l2_table_offset(RO_MPT_VIRT_START)] =
l2e_create_phys(pagetable_val(d->arch.phys_table),
l2e_create_phys(pagetable_get_phys(d->arch.phys_table),
__PAGE_HYPERVISOR);
if ( unlikely(!(hl2mfn = __shadow_status(d, gpfn, PGT_hl2_shadow))) )
@@ -2391,7 +2392,10 @@ static int resync_all(struct domain *d, u32 stype)
changed = 0;
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
{
if ( !is_guest_l2_slot(i) && !external )
#if CONFIG_X86_PAE
BUG(); /* FIXME: need type_info */
#endif
if ( !is_guest_l2_slot(0,i) && !external )
continue;
l2_pgentry_t new_pde = guest2[i];
@@ -2434,7 +2438,10 @@ static int resync_all(struct domain *d, u32 stype)
changed = 0;
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
{
if ( !is_guest_l2_slot(i) && !external )
#if CONFIG_X86_PAE
BUG(); /* FIXME: need type_info */
#endif
if ( !is_guest_l2_slot(0, i) && !external )
continue;
l2_pgentry_t new_pde = guest2[i];
@@ -2647,8 +2654,8 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
&gpte, sizeof(gpte))) )
{
printk("%s() failed, crashing domain %d "
"due to a read-only L2 page table (gpde=%lx), va=%lx\n",
__func__, d->domain_id, l2e_get_value(gpde), va);
"due to a read-only L2 page table (gpde=%" PRIpte "), va=%lx\n",
__func__,d->domain_id, l2e_get_value(gpde), va);
domain_crash_synchronous();
}
@@ -2721,7 +2728,7 @@ void shadow_l2_normal_pt_update(
shadow_unlock(d);
}
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
void shadow_l3_normal_pt_update(
struct domain *d,
unsigned long pa, l3_pgentry_t gpde,
@@ -2729,7 +2736,9 @@ void shadow_l3_normal_pt_update(
{
BUG(); // not yet implemented
}
#endif
#if CONFIG_PAGING_LEVELS >= 4
void shadow_l4_normal_pt_update(
struct domain *d,
unsigned long pa, l4_pgentry_t gpde,
+1 -1
View File
@@ -797,7 +797,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
break;
case 3: /* Read CR3 */
*reg = pagetable_val(ed->arch.guest_table);
*reg = pagetable_get_phys(ed->arch.guest_table);
break;
default:
+6 -6
View File
@@ -567,7 +567,7 @@ vmx_world_restore(struct exec_domain *d, struct vmx_assist_context *c)
if (!vmx_paging_enabled(d)) {
VMX_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
__vmwrite(GUEST_CR3, pagetable_val(d->domain->arch.phys_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(d->domain->arch.phys_table));
goto skip_cr3;
}
@@ -578,7 +578,7 @@ vmx_world_restore(struct exec_domain *d, struct vmx_assist_context *c)
* We simply invalidate the shadow.
*/
mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
if ((mfn << PAGE_SHIFT) != pagetable_val(d->arch.guest_table)) {
if (mfn != pagetable_get_pfn(d->arch.guest_table)) {
printk("Invalid CR3 value=%lx", c->cr3);
domain_crash_synchronous();
return 0;
@@ -603,7 +603,7 @@ vmx_world_restore(struct exec_domain *d, struct vmx_assist_context *c)
*/
d->arch.arch_vmx.cpu_cr3 = c->cr3;
VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", c->cr3);
__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(d->arch.shadow_table));
}
skip_cr3:
@@ -769,7 +769,7 @@ static int vmx_set_cr0(unsigned long value)
VMX_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
(unsigned long) (mfn << PAGE_SHIFT));
__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(d->arch.shadow_table));
/*
* arch->shadow_table should hold the next CR3 for shadow
*/
@@ -869,7 +869,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
* We simply invalidate the shadow.
*/
mfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
if ((mfn << PAGE_SHIFT) != pagetable_val(d->arch.guest_table))
if (mfn != pagetable_get_pfn(d->arch.guest_table))
__vmx_bug(regs);
shadow_sync_all(d->domain);
} else {
@@ -896,7 +896,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
d->arch.arch_vmx.cpu_cr3 = value;
VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx",
value);
__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(d->arch.shadow_table));
}
break;
}
+3 -3
View File
@@ -466,12 +466,12 @@ void vmx_do_resume(struct exec_domain *d)
{
vmx_stts();
if ( vmx_paging_enabled(d) )
__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(d->arch.shadow_table));
else
// paging is not enabled in the guest
__vmwrite(GUEST_CR3, pagetable_val(d->domain->arch.phys_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(d->domain->arch.phys_table));
__vmwrite(HOST_CR3, pagetable_val(d->arch.monitor_table));
__vmwrite(HOST_CR3, pagetable_get_phys(d->arch.monitor_table));
__vmwrite(HOST_ESP, (unsigned long)get_stack_bottom());
if (event_pending(d)) {
+2 -2
View File
@@ -196,8 +196,8 @@ void vmx_do_launch(struct exec_domain *ed)
error |= __vmwrite(GUEST_TR_BASE, 0);
error |= __vmwrite(GUEST_TR_LIMIT, 0xff);
__vmwrite(GUEST_CR3, pagetable_val(ed->arch.guest_table));
__vmwrite(HOST_CR3, pagetable_val(ed->arch.monitor_table));
__vmwrite(GUEST_CR3, pagetable_get_phys(ed->arch.guest_table));
__vmwrite(HOST_CR3, pagetable_get_phys(ed->arch.monitor_table));
__vmwrite(HOST_ESP, (unsigned long)get_stack_bottom());
ed->arch.schedule_tail = arch_vmx_do_resume;
+1 -1
View File
@@ -72,7 +72,7 @@ void *map_domain_mem(unsigned long pa)
shadow_epoch[cpu] = ++epoch;
}
}
while ( l1e_get_value(cache[idx]) != 0 );
while ( l1e_get_flags(cache[idx]) & _PAGE_PRESENT );
cache[idx] = l1e_create_phys(pa, __PAGE_HYPERVISOR);
+89 -49
View File
@@ -27,6 +27,8 @@
#include <asm/fixmap.h>
#include <asm/domain_page.h>
static unsigned long mpt_size;
struct pfn_info *alloc_xen_pagetable(void)
{
extern int early_boot;
@@ -51,69 +53,102 @@ void free_xen_pagetable(struct pfn_info *pg)
l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
{
return &idle_pg_table[l2_table_offset(v)];
return &idle_pg_table_l2[l2_linear_offset(v)];
}
void __init paging_init(void)
{
void *ioremap_pt;
unsigned long v;
struct pfn_info *m2p_pg;
unsigned long v,v2,i;
struct pfn_info *pg;
/* Allocate and map the machine-to-phys table. */
if ( (m2p_pg = alloc_domheap_pages(NULL, 10)) == NULL )
panic("Not enough memory to bootstrap Xen.\n");
idle_pg_table[l2_table_offset(RDWR_MPT_VIRT_START)] =
l2e_create_page(m2p_pg, __PAGE_HYPERVISOR | _PAGE_PSE);
memset((void *)RDWR_MPT_VIRT_START, 0x55, 4UL << 20);
#ifdef CONFIG_X86_PAE
printk("PAE enabled, limit: %d GB\n", MACHPHYS_MBYTES);
#else
printk("PAE disabled.\n");
#endif
/* Xen 4MB mappings can all be GLOBAL. */
idle0_exec_domain.arch.monitor_table = mk_pagetable(__pa(idle_pg_table));
/* Allocate and map the machine-to-phys table and create read-only
* mapping of MPT for guest-OS use. Without PAE we'll end up with
* one 4MB page, with PAE we'll allocate 2MB pages depending on
* the amout of memory installed, but at least 4MB to cover 4GB
* address space. This is needed to make PCI I/O memory address
* lookups work in guests. -- kraxel */
mpt_size = max_page * 4;
if (mpt_size < 4*1024*1024)
mpt_size = 4*1024*1024;
for (v = RDWR_MPT_VIRT_START, v2 = RO_MPT_VIRT_START;
v != RDWR_MPT_VIRT_END && mpt_size > (v - RDWR_MPT_VIRT_START);
v += (1 << L2_PAGETABLE_SHIFT), v2 += (1 << L2_PAGETABLE_SHIFT)) {
if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER)) == NULL )
panic("Not enough memory to bootstrap Xen.\n");
idle_pg_table_l2[l2_linear_offset(v)] =
l2e_create_page(pg, __PAGE_HYPERVISOR | _PAGE_PSE);
idle_pg_table_l2[l2_linear_offset(v2)] =
l2e_create_page(pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW);
}
memset((void *)RDWR_MPT_VIRT_START, 0x55, mpt_size);
/* Xen 2/4MB mappings can all be GLOBAL. */
if ( cpu_has_pge )
{
for ( v = HYPERVISOR_VIRT_START; v; v += (1 << L2_PAGETABLE_SHIFT) )
{
if (l2e_get_flags(idle_pg_table[l2_table_offset(v)]) & _PAGE_PSE)
l2e_add_flags(&idle_pg_table[l2_table_offset(v)],
_PAGE_GLOBAL);
for ( v = HYPERVISOR_VIRT_START; v; v += (1 << L2_PAGETABLE_SHIFT) ) {
if (!l2e_get_flags(idle_pg_table_l2[l2_linear_offset(v)]) & _PAGE_PSE)
continue;
if (v >= RO_MPT_VIRT_START && v < RO_MPT_VIRT_END)
continue;
l2e_add_flags(&idle_pg_table_l2[l2_linear_offset(v)],
_PAGE_GLOBAL);
}
}
/* Create page table for ioremap(). */
ioremap_pt = (void *)alloc_xenheap_page();
clear_page(ioremap_pt);
idle_pg_table[l2_table_offset(IOREMAP_VIRT_START)] =
l2e_create_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR);
/*
* Create read-only mapping of MPT for guest-OS use.
* NB. Remove the global bit so that shadow_mode_translate()==true domains
* can reused this address space for their phys-to-machine mapping.
*/
idle_pg_table[l2_table_offset(RO_MPT_VIRT_START)] =
l2e_create_page(m2p_pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW);
/* Create page table(s) for ioremap(). */
for (v = IOREMAP_VIRT_START; v != IOREMAP_VIRT_END; v += (1 << L2_PAGETABLE_SHIFT)) {
ioremap_pt = (void *)alloc_xenheap_page();
clear_page(ioremap_pt);
idle_pg_table_l2[l2_linear_offset(v)] =
l2e_create_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR);
}
/* Set up mapping cache for domain pages. */
mapcache = (l1_pgentry_t *)alloc_xenheap_page();
clear_page(mapcache);
idle_pg_table[l2_table_offset(MAPCACHE_VIRT_START)] =
l2e_create_page(virt_to_page(mapcache), __PAGE_HYPERVISOR);
mapcache = (l1_pgentry_t*)alloc_xenheap_pages(10-PAGETABLE_ORDER);
for (v = MAPCACHE_VIRT_START, i = 0;
v != MAPCACHE_VIRT_END;
v += (1 << L2_PAGETABLE_SHIFT), i++) {
clear_page(mapcache + i*L1_PAGETABLE_ENTRIES);
idle_pg_table_l2[l2_linear_offset(v)] =
l2e_create_page(virt_to_page(mapcache + i*L1_PAGETABLE_ENTRIES),
__PAGE_HYPERVISOR);
}
/* Set up linear page table mapping. */
idle_pg_table[l2_table_offset(LINEAR_PT_VIRT_START)] =
l2e_create_page(virt_to_page(idle_pg_table), __PAGE_HYPERVISOR);
for (v = LINEAR_PT_VIRT_START; v != LINEAR_PT_VIRT_END; v += (1 << L2_PAGETABLE_SHIFT)) {
idle_pg_table_l2[l2_linear_offset(v)] =
l2e_create_page(virt_to_page(idle_pg_table_l2 + ((v-RDWR_MPT_VIRT_START) >> PAGETABLE_ORDER)),
__PAGE_HYPERVISOR);
}
}
void __init zap_low_mappings(void)
void __init zap_low_mappings(l2_pgentry_t *base)
{
int i;
for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
idle_pg_table[i] = l2e_empty();
u32 addr;
for (i = 0; ; i++) {
addr = (i << L2_PAGETABLE_SHIFT);
if (addr >= HYPERVISOR_VIRT_START)
break;
if (l2e_get_phys(base[i]) != addr)
continue;
base[i] = l2e_empty();
}
flush_tlb_all_pge();
}
void subarch_init_memory(struct domain *dom_xen)
{
unsigned long i, m2p_start_mfn;
unsigned long i, v, m2p_start_mfn;
/*
* We are rather picky about the layout of 'struct pfn_info'. The
@@ -129,19 +164,24 @@ void subarch_init_memory(struct domain *dom_xen)
offsetof(struct pfn_info, count_info),
offsetof(struct pfn_info, u.inuse._domain),
sizeof(struct pfn_info));
for ( ; ; ) ;
for ( ; ; )
__asm__ __volatile__ ( "hlt" );
}
/* M2P table is mappable read-only by privileged domains. */
m2p_start_mfn = l2e_get_pfn(
idle_pg_table[l2_table_offset(RDWR_MPT_VIRT_START)]);
for ( i = 0; i < 1024; i++ )
{
frame_table[m2p_start_mfn+i].count_info = PGC_allocated | 1;
/* gdt to make sure it's only mapped read-only by non-privileged
domains. */
frame_table[m2p_start_mfn+i].u.inuse.type_info = PGT_gdt_page | 1;
page_set_owner(&frame_table[m2p_start_mfn+i], dom_xen);
for (v = RDWR_MPT_VIRT_START;
v != RDWR_MPT_VIRT_END && mpt_size > (v - RDWR_MPT_VIRT_START);
v += (1 << L2_PAGETABLE_SHIFT)) {
m2p_start_mfn = l2e_get_pfn(
idle_pg_table_l2[l2_linear_offset(v)]);
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
{
frame_table[m2p_start_mfn+i].count_info = PGC_allocated | 1;
/* gdt to make sure it's only mapped read-only by non-privileged
domains. */
frame_table[m2p_start_mfn+i].u.inuse.type_info = PGT_gdt_page | 1;
page_set_owner(&frame_table[m2p_start_mfn+i], dom_xen);
}
}
}
+10 -7
View File
@@ -92,21 +92,24 @@ void show_registers(struct cpu_user_regs *regs)
void show_page_walk(unsigned long addr)
{
unsigned long page;
l2_pgentry_t pmd;
l1_pgentry_t *pte;
if ( addr < PAGE_OFFSET )
return;
printk("Pagetable walk from %08lx:\n", addr);
page = l2e_get_value(idle_pg_table[l2_table_offset(addr)]);
printk(" L2 = %08lx %s\n", page, (page & _PAGE_PSE) ? "(4MB)" : "");
if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) )
pmd = idle_pg_table_l2[l2_linear_offset(addr)];
printk(" L2 = %08llx %s\n", (u64)l2e_get_value(pmd),
(l2e_get_flags(pmd) & _PAGE_PSE) ? "(2/4MB)" : "");
if ( !(l2e_get_flags(pmd) & _PAGE_PRESENT) ||
(l2e_get_flags(pmd) & _PAGE_PSE) )
return;
page &= PAGE_MASK;
page = ((unsigned long *) __va(page))[l1_table_offset(addr)];
printk(" L1 = %08lx\n", page);
pte = __va(l2e_get_phys(pmd));
pte += l1_table_offset(addr);
printk(" L1 = %08llx\n", (u64)l1e_get_value(*pte));
}
#define DOUBLEFAULT_STACK_SIZE 1024
+2
View File
@@ -79,6 +79,8 @@ void __init paging_init(void)
l2_pgentry_t *l2_ro_mpt;
struct pfn_info *pg;
idle0_exec_domain.arch.monitor_table = mk_pagetable(__pa(idle_pg_table));
/* Create user-accessible L2 directory to map the MPT for guests. */
l3_ro_mpt = (l3_pgentry_t *)alloc_xenheap_page();
clear_page(l3_ro_mpt);
+23 -10
View File
@@ -7,6 +7,19 @@
#ifndef __X86_CONFIG_H__
#define __X86_CONFIG_H__
#if defined(__i386__)
// # define CONFIG_X86_PAE 1 /* yes */
# undef CONFIG_X86_PAE /* no */
#endif
#if defined(__x86_64__)
# define CONFIG_PAGING_LEVELS 4
#elif defined(CONFIG_X86_PAE)
# define CONFIG_PAGING_LEVELS 3
#else
# define CONFIG_PAGING_LEVELS 2
#endif
#define CONFIG_X86 1
#define CONFIG_X86_HT 1
#define CONFIG_SHADOW 1
@@ -189,7 +202,7 @@ extern unsigned long _end; /* standard ELF symbol */
* Per-domain mappings ( 4MB)
* Shadow linear pagetable ( 4MB) ( 8MB)
* Guest linear pagetable ( 4MB) ( 8MB)
* Machine-to-physical translation table [writable] ( 4MB)
* Machine-to-physical translation table [writable] ( 4MB) (16MB)
* Frame-info table (24MB) (96MB)
* * Start of guest inaccessible area
* Machine-to-physical translation table [read-only] ( 4MB)
@@ -203,8 +216,8 @@ extern unsigned long _end; /* standard ELF symbol */
#ifdef CONFIG_X86_PAE
# define LINEARPT_MBYTES 8
# define MACHPHYS_MBYTES 4 /* KAF: This needs to be bigger */
# define FRAMETABLE_MBYTES 96 /* 16 GB mem limit (total) */
# define MACHPHYS_MBYTES 16 /* 1 MB needed per 1 GB memory */
# define FRAMETABLE_MBYTES (MACHPHYS_MBYTES * 6)
#else
# define LINEARPT_MBYTES 4
# define MACHPHYS_MBYTES 4
@@ -237,21 +250,21 @@ extern unsigned long _end; /* standard ELF symbol */
#define GUEST_SEGMENT_MAX_ADDR RO_MPT_VIRT_END
#ifdef CONFIG_X86_PAE
/* Hypervisor owns top 144MB of virtual address space. */
# define __HYPERVISOR_VIRT_START 0xF7000000
# define HYPERVISOR_VIRT_START (0xF7000000UL)
/* Hypervisor owns top 168MB of virtual address space. */
# define __HYPERVISOR_VIRT_START 0xF5800000
# define HYPERVISOR_VIRT_START (0xF5800000UL)
#else
/* Hypervisor owns top 64MB of virtual address space. */
# define __HYPERVISOR_VIRT_START 0xFC000000
# define HYPERVISOR_VIRT_START (0xFC000000UL)
#endif
#define ROOT_PAGETABLE_FIRST_XEN_SLOT \
#define L2_PAGETABLE_FIRST_XEN_SLOT \
(HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT)
#define ROOT_PAGETABLE_LAST_XEN_SLOT \
#define L2_PAGETABLE_LAST_XEN_SLOT \
(~0UL >> L2_PAGETABLE_SHIFT)
#define ROOT_PAGETABLE_XEN_SLOTS \
(ROOT_PAGETABLE_LAST_XEN_SLOT - ROOT_PAGETABLE_FIRST_XEN_SLOT + 1)
#define L2_PAGETABLE_XEN_SLOTS \
(L2_PAGETABLE_LAST_XEN_SLOT - L2_PAGETABLE_FIRST_XEN_SLOT + 1)
#define PGT_base_page_table PGT_l2_page_table
-6
View File
@@ -119,12 +119,6 @@ struct arch_exec_domain
unsigned long shadow_ldt_mapcnt;
} __cacheline_aligned;
#define IDLE0_ARCH_EXEC_DOMAIN \
{ \
perdomain_ptes: 0, \
monitor_table: mk_pagetable(__pa(idle_pg_table)) \
}
#endif /* __ASM_DOMAIN_H__ */
/*
+7 -7
View File
@@ -76,15 +76,15 @@ struct pfn_info
/* Owning guest has pinned this page to its current type? */
#define _PGT_pinned 27
#define PGT_pinned (1U<<_PGT_pinned)
/* The 10 most significant bits of virt address if this is a page table. */
#define PGT_va_shift 17
#define PGT_va_mask (((1U<<10)-1)<<PGT_va_shift)
/* The 11 most significant bits of virt address if this is a page table. */
#define PGT_va_shift 16
#define PGT_va_mask (((1U<<11)-1)<<PGT_va_shift)
/* Is the back pointer still mutable (i.e. not fixed yet)? */
#define PGT_va_mutable (((1U<<10)-1)<<PGT_va_shift)
#define PGT_va_mutable (((1U<<11)-1)<<PGT_va_shift)
/* Is the back pointer unknown (e.g., p.t. is mapped at multiple VAs)? */
#define PGT_va_unknown (((1U<<10)-2)<<PGT_va_shift)
/* 17-bit count of uses of this frame as its current type. */
#define PGT_count_mask ((1U<<17)-1)
#define PGT_va_unknown (((1U<<11)-2)<<PGT_va_shift)
/* 16-bit count of uses of this frame as its current type. */
#define PGT_count_mask ((1U<<16)-1)
#define PGT_mfn_mask ((1U<<20)-1) /* mfn mask for shadow types */
+134 -17
View File
@@ -8,23 +8,132 @@
#define PAGE_SIZE (1 << PAGE_SHIFT)
#endif
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_FLAG_MASK (~0U)
#ifndef __ASSEMBLY__
# include <asm/types.h>
#endif
#if defined(__i386__)
#include <asm/x86_32/page.h>
# include <asm/x86_32/page.h>
#elif defined(__x86_64__)
#include <asm/x86_64/page.h>
# include <asm/x86_64/page.h>
#endif
/* Get pte contents as an integer (intpte_t). */
#define l1e_get_value(x) ((x).l1)
#define l2e_get_value(x) ((x).l2)
#define l3e_get_value(x) ((x).l3)
#define l4e_get_value(x) ((x).l4)
/* Get pfn mapped by pte (unsigned long). */
#define l1e_get_pfn(x) \
((unsigned long)(((x).l1 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
#define l2e_get_pfn(x) \
((unsigned long)(((x).l2 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
#define l3e_get_pfn(x) \
((unsigned long)(((x).l3 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
#define l4e_get_pfn(x) \
((unsigned long)(((x).l4 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
/* Get physical address of page mapped by pte (physaddr_t). */
#define l1e_get_phys(x) \
((physaddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
#define l2e_get_phys(x) \
((physaddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
#define l3e_get_phys(x) \
((physaddr_t)(((x).l3 & (PADDR_MASK&PAGE_MASK))))
#define l4e_get_phys(x) \
((physaddr_t)(((x).l4 & (PADDR_MASK&PAGE_MASK))))
/* Get pte access flags (unsigned int). */
#define l1e_get_flags(x) (get_pte_flags((x).l1))
#define l2e_get_flags(x) (get_pte_flags((x).l2))
#define l3e_get_flags(x) (get_pte_flags((x).l3))
#define l4e_get_flags(x) (get_pte_flags((x).l4))
/* Construct an empty pte. */
#define l1e_empty() ((l1_pgentry_t) { 0 })
#define l2e_empty() ((l2_pgentry_t) { 0 })
#define l3e_empty() ((l3_pgentry_t) { 0 })
#define l4e_empty() ((l4_pgentry_t) { 0 })
/* Construct a pte from a pfn and access flags. */
#define l1e_create_pfn(pfn, flags) \
((l1_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
#define l2e_create_pfn(pfn, flags) \
((l2_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
#define l3e_create_pfn(pfn, flags) \
((l3_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
#define l4e_create_pfn(pfn, flags) \
((l4_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
/* Construct a pte from a physical address and access flags. */
#define l1e_create_phys(pa, flags) \
((l1_pgentry_t) { (pa) | put_pte_flags(flags) })
#define l2e_create_phys(pa, flags) \
((l2_pgentry_t) { (pa) | put_pte_flags(flags) })
#define l3e_create_phys(pa, flags) \
((l3_pgentry_t) { (pa) | put_pte_flags(flags) })
#define l4e_create_phys(pa, flags) \
((l4_pgentry_t) { (pa) | put_pte_flags(flags) })
/* Add extra flags to an existing pte. */
#define l1e_add_flags(x, flags) ((x)->l1 |= put_pte_flags(flags))
#define l2e_add_flags(x, flags) ((x)->l2 |= put_pte_flags(flags))
#define l3e_add_flags(x, flags) ((x)->l3 |= put_pte_flags(flags))
#define l4e_add_flags(x, flags) ((x)->l4 |= put_pte_flags(flags))
/* Remove flags from an existing pte. */
#define l1e_remove_flags(x, flags) ((x)->l1 &= ~put_pte_flags(flags))
#define l2e_remove_flags(x, flags) ((x)->l2 &= ~put_pte_flags(flags))
#define l3e_remove_flags(x, flags) ((x)->l3 &= ~put_pte_flags(flags))
#define l4e_remove_flags(x, flags) ((x)->l4 &= ~put_pte_flags(flags))
/* Check if a pte's page mapping or significant access flags have changed. */
#define l1e_has_changed(x,y,flags) \
( !!(((x)->l1 ^ (y)->l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
#define l2e_has_changed(x,y,flags) \
( !!(((x)->l2 ^ (y)->l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
#define l3e_has_changed(x,y,flags) \
( !!(((x)->l3 ^ (y)->l3) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
#define l4e_has_changed(x,y,flags) \
( !!(((x)->l4 ^ (y)->l4) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
/* Pagetable walking. */
#define l2e_to_l1e(x) ((l1_pgentry_t *)__va(l2e_get_phys(x)))
#define l3e_to_l2e(x) ((l2_pgentry_t *)__va(l3e_get_phys(x)))
#define l4e_to_l3e(x) ((l3_pgentry_t *)__va(l4e_get_phys(x)))
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(a) \
(((a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
#define l2_table_offset(a) \
(((a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
#define l3_table_offset(a) \
(((a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
#define l4_table_offset(a) \
(((a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
/* Convert a pointer to a page-table entry into pagetable slot index. */
#define pgentry_ptr_to_slot(_p) \
(((unsigned long)(_p) & ~PAGE_MASK) / sizeof(*(_p)))
/* Page-table type. */
#ifndef __ASSEMBLY__
typedef struct { unsigned long pt_lo; } pagetable_t;
#define pagetable_val(_x) ((_x).pt_lo)
#define pagetable_get_pfn(_x) ((_x).pt_lo >> PAGE_SHIFT)
#define mk_pagetable(_x) ( (pagetable_t) { (_x) } )
#if CONFIG_PAGING_LEVELS == 2
/* x86_32 default */
typedef struct { u32 pfn; } pagetable_t;
#elif CONFIG_PAGING_LEVELS == 3
/* x86_32 PAE */
typedef struct { u32 pfn; } pagetable_t;
#elif CONFIG_PAGING_LEVELS == 4
/* x86_64 */
typedef struct { u64 pfn; } pagetable_t;
#endif
#define pagetable_get_phys(_x) ((physaddr_t)(_x).pfn << PAGE_SHIFT)
#define pagetable_get_pfn(_x) ((_x).pfn)
#define mk_pagetable(_phys) ({ pagetable_t __p; __p.pfn = _phys >> PAGE_SHIFT; __p; })
#endif
#define clear_page(_p) memset((void *)(_p), 0, PAGE_SIZE)
@@ -49,6 +158,7 @@ typedef struct { unsigned long pt_lo; } pagetable_t;
#define l4e_create_page(_x,_y) (l4e_create_pfn(page_to_pfn(_x),(_y)))
/* High table entries are reserved by the hypervisor. */
/* FIXME: this breaks with PAE -- kraxel */
#define DOMAIN_ENTRIES_PER_L2_PAGETABLE \
(HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT)
#define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE \
@@ -78,7 +188,14 @@ typedef struct { unsigned long pt_lo; } pagetable_t;
(l2e_get_pfn(linear_l2_table(_ed)[_va>>L2_PAGETABLE_SHIFT]))
#ifndef __ASSEMBLY__
#if CONFIG_PAGING_LEVELS == 3
extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES];
extern l3_pgentry_t idle_pg_table_l3[ROOT_PAGETABLE_ENTRIES];
extern l2_pgentry_t idle_pg_table_l2[ROOT_PAGETABLE_ENTRIES*L2_PAGETABLE_ENTRIES];
#else
extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES];
extern l2_pgentry_t idle_pg_table_l2[ROOT_PAGETABLE_ENTRIES];
#endif
extern void paging_init(void);
#endif
@@ -96,17 +213,17 @@ extern void paging_init(void);
: : "r" (mmu_cr4_features) ); \
} while ( 0 )
#define _PAGE_PRESENT 0x001UL
#define _PAGE_RW 0x002UL
#define _PAGE_USER 0x004UL
#define _PAGE_PWT 0x008UL
#define _PAGE_PCD 0x010UL
#define _PAGE_ACCESSED 0x020UL
#define _PAGE_DIRTY 0x040UL
#define _PAGE_PAT 0x080UL
#define _PAGE_PSE 0x080UL
#define _PAGE_GLOBAL 0x100UL
#define _PAGE_AVAIL 0xe00UL
#define _PAGE_PRESENT 0x001U
#define _PAGE_RW 0x002U
#define _PAGE_USER 0x004U
#define _PAGE_PWT 0x008U
#define _PAGE_PCD 0x010U
#define _PAGE_ACCESSED 0x020U
#define _PAGE_DIRTY 0x040U
#define _PAGE_PAT 0x080U
#define _PAGE_PSE 0x080U
#define _PAGE_GLOBAL 0x100U
#define _PAGE_AVAIL 0xE00U
#define __PAGE_HYPERVISOR \
(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+4 -2
View File
@@ -130,10 +130,12 @@ extern void shadow_l1_normal_pt_update(struct domain *d,
extern void shadow_l2_normal_pt_update(struct domain *d,
unsigned long pa, l2_pgentry_t l2e,
struct map_dom_mem_cache *cache);
#ifdef __x86_64__
#if CONFIG_PAGING_LEVELS >= 3
extern void shadow_l3_normal_pt_update(struct domain *d,
unsigned long pa, l3_pgentry_t l3e,
struct map_dom_mem_cache *cache);
#endif
#if CONFIG_PAGING_LEVELS >= 4
extern void shadow_l4_normal_pt_update(struct domain *d,
unsigned long pa, l4_pgentry_t l4e,
struct map_dom_mem_cache *cache);
@@ -1682,7 +1684,7 @@ static inline void update_pagetables(struct exec_domain *ed)
// HACK ALERT: there's currently no easy way to figure out if a domU
// has set its arch.guest_table to zero, vs not yet initialized it.
//
paging_enabled = !!pagetable_val(ed->arch.guest_table);
paging_enabled = !!pagetable_get_phys(ed->arch.guest_table);
/*
* We don't call __update_pagetables() when vmx guest paging is
+6 -1
View File
@@ -39,7 +39,12 @@ extern cpumask_t cpu_sibling_map[];
extern void smp_flush_tlb(void);
extern void smp_invalidate_rcv(void); /* Process an NMI */
extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
#ifdef CONFIG_X86_64
extern void zap_low_mappings(void);
#else
extern void zap_low_mappings(l2_pgentry_t *base);
#endif
#define MAX_APICID 256
extern u8 x86_cpu_to_apicid[];
+6
View File
@@ -44,11 +44,17 @@ typedef signed long long s64;
typedef unsigned long long u64;
#define BITS_PER_LONG 32
typedef unsigned int size_t;
#if defined(CONFIG_X86_PAE)
typedef u64 physaddr_t;
#else
typedef u32 physaddr_t;
#endif
#elif defined(__x86_64__)
typedef signed long s64;
typedef unsigned long u64;
#define BITS_PER_LONG 64
typedef unsigned long size_t;
typedef u64 physaddr_t;
#endif
/* DMA addresses come in generic and 64-bit flavours. */
+49
View File
@@ -0,0 +1,49 @@
#ifndef __X86_32_PAGE_2L_H__
#define __X86_32_PAGE_2L_H__
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#define ROOT_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT
#define PAGETABLE_ORDER 10
#define L1_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define L2_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define ROOT_PAGETABLE_ENTRIES L2_PAGETABLE_ENTRIES
#define PADDR_BITS 32
#define PADDR_MASK (~0UL)
#ifndef __ASSEMBLY__
#include <asm/types.h>
/* read access (should only be used for debug printk's) */
typedef u32 intpte_t;
#define PRIpte "08x"
typedef struct { intpte_t l1; } l1_pgentry_t;
typedef struct { intpte_t l2; } l2_pgentry_t;
typedef l2_pgentry_t root_pgentry_t;
#endif /* !__ASSEMBLY__ */
/* root table */
#define root_get_pfn l2e_get_pfn
#define root_get_flags l2e_get_flags
#define root_get_value l2e_get_value
#define root_empty l2e_empty
#define root_create_phys l2e_create_phys
#define PGT_root_page_table PGT_l2_page_table
/* misc */
#define is_guest_l1_slot(_s) (1)
#define is_guest_l2_slot(_t,_s) ((_s) < L2_PAGETABLE_FIRST_XEN_SLOT)
#define get_pte_flags(x) ((int)(x) & 0xFFF)
#define put_pte_flags(x) ((intpte_t)(x))
#define L1_DISALLOW_MASK (0xFFFFF180U) /* PAT/GLOBAL */
#define L2_DISALLOW_MASK (0xFFFFF180U) /* PSE/GLOBAL */
#endif /* __X86_32_PAGE_2L_H__ */
+56
View File
@@ -0,0 +1,56 @@
#ifndef __X86_32_PAGE_3L_H__
#define __X86_32_PAGE_3L_H__
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 21
#define L3_PAGETABLE_SHIFT 30
#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#define ROOT_PAGETABLE_SHIFT L3_PAGETABLE_SHIFT
#define PAGETABLE_ORDER 9
#define L1_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define L2_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define L3_PAGETABLE_ENTRIES 4
#define ROOT_PAGETABLE_ENTRIES L3_PAGETABLE_ENTRIES
#define PADDR_BITS 52
#define PADDR_MASK ((1ULL << PADDR_BITS)-1)
#ifndef __ASSEMBLY__
#include <asm/types.h>
/* read access (should only be used for debug printk's) */
typedef u64 intpte_t;
#define PRIpte "016llx"
typedef struct { intpte_t l1; } l1_pgentry_t;
typedef struct { intpte_t l2; } l2_pgentry_t;
typedef struct { intpte_t l3; } l3_pgentry_t;
typedef l3_pgentry_t root_pgentry_t;
#endif /* !__ASSEMBLY__ */
/* root table */
#define root_get_pfn l3e_get_pfn
#define root_get_flags l3e_get_flags
#define root_get_value l3e_get_value
#define root_empty l3e_empty
#define root_init_phys l3e_create_phys
#define PGT_root_page_table PGT_l3_page_table
/* misc */
#define is_guest_l1_slot(_s) (1)
#define is_guest_l2_slot(_t,_s) \
((3 != (((_t) & PGT_va_mask) >> PGT_va_shift)) || \
((_s) < (L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1))))
#define is_guest_l3_slot(_s) (1)
#define get_pte_flags(x) ((int)((x) >> 40) | ((int)(x) & 0xFFF))
#define put_pte_flags(x) ((((intpte_t)((x) & ~0xFFF)) << 40) | ((x) & 0xFFF))
#define L1_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PAT/GLOBAL */
#define L2_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PSE/GLOBAL */
#define L3_DISALLOW_MASK (0xFFFFF1E6U) /* must-be-zero */
#endif /* __X86_32_PAGE_3L_H__ */
+8 -119
View File
@@ -2,134 +2,23 @@
#ifndef __X86_32_PAGE_H__
#define __X86_32_PAGE_H__
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#define ROOT_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT
#define PAGETABLE_ORDER 10
#define L1_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define L2_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define ROOT_PAGETABLE_ENTRIES L2_PAGETABLE_ENTRIES
#define __PAGE_OFFSET (0xFF000000)
#define PADDR_BITS 32
#define VADDR_BITS 32
#define PADDR_MASK (~0UL)
#define VADDR_MASK (~0UL)
#define _PAGE_NX 0UL
#define PAGE_FLAG_MASK 0xfff
#define _PAGE_NX 0U
#ifndef __ASSEMBLY__
#include <xen/config.h>
#include <asm/types.h>
typedef struct { u32 l1_lo; } l1_pgentry_t;
typedef struct { u32 l2_lo; } l2_pgentry_t;
typedef l2_pgentry_t root_pgentry_t;
/* read access (deprecated) */
#define l1e_get_value(_x) ((unsigned long)((_x).l1_lo))
#define l2e_get_value(_x) ((unsigned long)((_x).l2_lo))
/* read access */
#define l1e_get_pfn(_x) ((unsigned long)((_x).l1_lo >> PAGE_SHIFT))
#define l1e_get_phys(_x) ((unsigned long)((_x).l1_lo & PAGE_MASK))
#define l1e_get_flags(_x) ((unsigned long)((_x).l1_lo & PAGE_FLAG_MASK))
#define l2e_get_pfn(_x) ((unsigned long)((_x).l2_lo >> PAGE_SHIFT))
#define l2e_get_phys(_x) ((unsigned long)((_x).l2_lo & PAGE_MASK))
#define l2e_get_flags(_x) ((unsigned long)((_x).l2_lo & PAGE_FLAG_MASK))
/* write access */
static inline l1_pgentry_t l1e_empty(void)
{
l1_pgentry_t e = { .l1_lo = 0 };
return e;
}
static inline l1_pgentry_t l1e_create_pfn(u32 pfn, u32 flags)
{
l1_pgentry_t e = { .l1_lo = (pfn << PAGE_SHIFT) | flags };
return e;
}
static inline l1_pgentry_t l1e_create_phys(u32 addr, u32 flags)
{
l1_pgentry_t e = { .l1_lo = (addr & PAGE_MASK) | flags };
return e;
}
static inline void l1e_add_flags(l1_pgentry_t *e, u32 flags)
{
e->l1_lo |= flags;
}
static inline void l1e_remove_flags(l1_pgentry_t *e, u32 flags)
{
e->l1_lo &= ~flags;
}
static inline l2_pgentry_t l2e_empty(void)
{
l2_pgentry_t e = { .l2_lo = 0 };
return e;
}
static inline l2_pgentry_t l2e_create_pfn(u32 pfn, u32 flags)
{
l2_pgentry_t e = { .l2_lo = (pfn << PAGE_SHIFT) | flags };
return e;
}
static inline l2_pgentry_t l2e_create_phys(u32 addr, u32 flags)
{
l2_pgentry_t e = { .l2_lo = (addr & PAGE_MASK) | flags };
return e;
}
static inline void l2e_add_flags(l2_pgentry_t *e, u32 flags)
{
e->l2_lo |= flags;
}
static inline void l2e_remove_flags(l2_pgentry_t *e, u32 flags)
{
e->l2_lo &= ~flags;
}
/* check entries */
static inline int l1e_has_changed(l1_pgentry_t *e1, l1_pgentry_t *e2, u32 flags)
{
return ((e1->l1_lo ^ e2->l1_lo) & (PAGE_MASK | flags)) != 0;
}
static inline int l2e_has_changed(l2_pgentry_t *e1, l2_pgentry_t *e2, u32 flags)
{
return ((e1->l2_lo ^ e2->l2_lo) & (PAGE_MASK | flags)) != 0;
}
#endif /* !__ASSEMBLY__ */
/* Pagetable walking. */
#define l2e_to_l1e(_x) \
((l1_pgentry_t *)__va(l2e_get_phys(_x)))
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
#define l2_table_offset(_a) \
((_a) >> L2_PAGETABLE_SHIFT)
#ifdef CONFIG_X86_PAE
# include <asm/x86_32/page-3level.h>
#else
# include <asm/x86_32/page-2level.h>
#endif
/* Given a virtual address, get an entry offset into a linear page table. */
#define l1_linear_offset(_a) ((_a) >> PAGE_SHIFT)
#define is_guest_l1_slot(_s) (1)
#define is_guest_l2_slot(_s) ((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT)
#define root_get_pfn l2e_get_pfn
#define root_get_flags l2e_get_flags
#define root_get_value l2e_get_value
#define root_empty l2e_empty
#define root_create_phys l2e_create_phys
#define PGT_root_page_table PGT_l2_page_table
#define L1_DISALLOW_MASK (3UL << 7)
#define L2_DISALLOW_MASK (7UL << 7)
#define L3_DISALLOW_MASK (7UL << 7)
#define L4_DISALLOW_MASK (7UL << 7)
#define l1_linear_offset(_a) ((_a) >> L1_PAGETABLE_SHIFT)
#define l2_linear_offset(_a) ((_a) >> L2_PAGETABLE_SHIFT)
#endif /* __X86_32_PAGE_H__ */
+20 -168
View File
@@ -24,181 +24,28 @@
#define PADDR_MASK ((1UL << PADDR_BITS)-1)
#define VADDR_MASK ((1UL << VADDR_BITS)-1)
#define _PAGE_NX (cpu_has_nx ? (1UL<<63) : 0UL)
#define PAGE_FLAG_MASK 0xfff
#ifndef __ASSEMBLY__
#include <xen/config.h>
#include <asm/types.h>
typedef struct { u64 l1_lo; } l1_pgentry_t;
typedef struct { u64 l2_lo; } l2_pgentry_t;
typedef struct { u64 l3_lo; } l3_pgentry_t;
typedef struct { u64 l4_lo; } l4_pgentry_t;
/* read access (should only be used for debug printk's) */
typedef u64 intpte_t;
#define PRIpte "016lx"
typedef struct { intpte_t l1; } l1_pgentry_t;
typedef struct { intpte_t l2; } l2_pgentry_t;
typedef struct { intpte_t l3; } l3_pgentry_t;
typedef struct { intpte_t l4; } l4_pgentry_t;
typedef l4_pgentry_t root_pgentry_t;
/* read access (depricated) */
#define l1e_get_value(_x) ((_x).l1_lo)
#define l2e_get_value(_x) ((_x).l2_lo)
#define l3e_get_value(_x) ((_x).l3_lo)
#define l4e_get_value(_x) ((_x).l4_lo)
/* read access */
#define l1e_get_pfn(_x) (((_x).l1_lo & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT)
#define l1e_get_phys(_x) (((_x).l1_lo & (PADDR_MASK&PAGE_MASK)))
#define l1e_get_flags(_x) ((_x).l1_lo & PAGE_FLAG_MASK)
#define l2e_get_pfn(_x) (((_x).l2_lo & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT)
#define l2e_get_phys(_x) (((_x).l2_lo & (PADDR_MASK&PAGE_MASK)))
#define l2e_get_flags(_x) ((_x).l2_lo & PAGE_FLAG_MASK)
#define l3e_get_pfn(_x) (((_x).l3_lo & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT)
#define l3e_get_phys(_x) (((_x).l3_lo & (PADDR_MASK&PAGE_MASK)))
#define l3e_get_flags(_x) ((_x).l3_lo & PAGE_FLAG_MASK)
#define l4e_get_pfn(_x) (((_x).l4_lo & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT)
#define l4e_get_phys(_x) (((_x).l4_lo & (PADDR_MASK&PAGE_MASK)))
#define l4e_get_flags(_x) ((_x).l4_lo & PAGE_FLAG_MASK)
/* write access */
static inline l1_pgentry_t l1e_empty(void)
{
l1_pgentry_t e = { .l1_lo = 0 };
return e;
}
static inline l1_pgentry_t l1e_create_pfn(u64 pfn, u64 flags)
{
l1_pgentry_t e = { .l1_lo = (pfn << PAGE_SHIFT) | flags };
return e;
}
static inline l1_pgentry_t l1e_create_phys(u64 addr, u64 flags)
{
l1_pgentry_t e = { .l1_lo = (addr & (PADDR_MASK&PAGE_MASK)) | flags };
return e;
}
static inline void l1e_add_flags(l1_pgentry_t *e, u64 flags)
{
e->l1_lo |= flags;
}
static inline void l1e_remove_flags(l1_pgentry_t *e, u64 flags)
{
e->l1_lo &= ~flags;
}
static inline l2_pgentry_t l2e_empty(void)
{
l2_pgentry_t e = { .l2_lo = 0 };
return e;
}
static inline l2_pgentry_t l2e_create_pfn(u64 pfn, u64 flags)
{
l2_pgentry_t e = { .l2_lo = (pfn << PAGE_SHIFT) | flags };
return e;
}
static inline l2_pgentry_t l2e_create_phys(u64 addr, u64 flags)
{
l2_pgentry_t e = { .l2_lo = (addr & (PADDR_MASK&PAGE_MASK)) | flags };
return e;
}
static inline void l2e_add_flags(l2_pgentry_t *e, u64 flags)
{
e->l2_lo |= flags;
}
static inline void l2e_remove_flags(l2_pgentry_t *e, u64 flags)
{
e->l2_lo &= ~flags;
}
static inline l3_pgentry_t l3e_empty(void)
{
l3_pgentry_t e = { .l3_lo = 0 };
return e;
}
static inline l3_pgentry_t l3e_create_pfn(u64 pfn, u64 flags)
{
l3_pgentry_t e = { .l3_lo = (pfn << PAGE_SHIFT) | flags };
return e;
}
static inline l3_pgentry_t l3e_create_phys(u64 addr, u64 flags)
{
l3_pgentry_t e = { .l3_lo = (addr & (PADDR_MASK&PAGE_MASK)) | flags };
return e;
}
static inline void l3e_add_flags(l3_pgentry_t *e, u64 flags)
{
e->l3_lo |= flags;
}
static inline void l3e_remove_flags(l3_pgentry_t *e, u64 flags)
{
e->l3_lo &= ~flags;
}
static inline l4_pgentry_t l4e_empty(void)
{
l4_pgentry_t e = { .l4_lo = 0 };
return e;
}
static inline l4_pgentry_t l4e_create_pfn(u64 pfn, u64 flags)
{
l4_pgentry_t e = { .l4_lo = (pfn << PAGE_SHIFT) | flags };
return e;
}
static inline l4_pgentry_t l4e_create_phys(u64 addr, u64 flags)
{
l4_pgentry_t e = { .l4_lo = (addr & (PADDR_MASK&PAGE_MASK)) | flags };
return e;
}
static inline void l4e_add_flags(l4_pgentry_t *e, u64 flags)
{
e->l4_lo |= flags;
}
static inline void l4e_remove_flags(l4_pgentry_t *e, u64 flags)
{
e->l4_lo &= ~flags;
}
/* check entries */
static inline int l1e_has_changed(l1_pgentry_t *e1, l1_pgentry_t *e2, u32 flags)
{
return ((e1->l1_lo ^ e2->l1_lo) & ((PADDR_MASK&PAGE_MASK) | flags)) != 0;
}
static inline int l2e_has_changed(l2_pgentry_t *e1, l2_pgentry_t *e2, u32 flags)
{
return ((e1->l2_lo ^ e2->l2_lo) & ((PADDR_MASK&PAGE_MASK) | flags)) != 0;
}
static inline int l3e_has_changed(l3_pgentry_t *e1, l3_pgentry_t *e2, u32 flags)
{
return ((e1->l3_lo ^ e2->l3_lo) & ((PADDR_MASK&PAGE_MASK) | flags)) != 0;
}
static inline int l4e_has_changed(l4_pgentry_t *e1, l4_pgentry_t *e2, u32 flags)
{
return ((e1->l4_lo ^ e2->l4_lo) & ((PADDR_MASK&PAGE_MASK) | flags)) != 0;
}
#endif /* !__ASSEMBLY__ */
/* Pagetable walking. */
#define l2e_to_l1e(_x) \
((l1_pgentry_t *)__va(l2e_get_phys(_x)))
#define l3e_to_l2e(_x) \
((l2_pgentry_t *)__va(l3e_get_phys(_x)))
#define l4e_to_l3e(_x) \
((l3_pgentry_t *)__va(l4e_get_phys(_x)))
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
#define l2_table_offset(_a) \
(((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
#define l3_table_offset(_a) \
(((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
#define l4_table_offset(_a) \
(((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
/* Given a virtual address, get an entry offset into a linear page table. */
#define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> PAGE_SHIFT)
#define is_guest_l1_slot(_s) (1)
#define is_guest_l2_slot(_s) (1)
#define is_guest_l2_slot(_t, _s) (1)
#define is_guest_l3_slot(_s) (1)
#define is_guest_l4_slot(_s) \
(((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT) || \
@@ -211,10 +58,15 @@ static inline int l4e_has_changed(l4_pgentry_t *e1, l4_pgentry_t *e2, u32 flags)
#define root_create_phys l4e_create_phys
#define PGT_root_page_table PGT_l4_page_table
#define L1_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (3UL << 7))
#define L2_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7))
#define L3_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7))
#define L4_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7))
#define get_pte_flags(x) ((int)((x) >> 40) | ((int)(x) & 0xFFF))
#define put_pte_flags(x) ((((intpte_t)((x) & ~0xFFF)) << 40) | ((x) & 0xFFF))
#define _PAGE_NX (cpu_has_nx ? (1U<<23) : 0U)
#define L1_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PAT/GLOBAL */
#define L2_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PSE/GLOBAL */
#define L3_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* must-be-zero */
#define L4_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* must-be-zero */
#endif /* __X86_64_PAGE_H__ */
+5 -1
View File
@@ -64,7 +64,11 @@
* Virtual addresses beyond this are not modifiable by guest OSes. The
* machine->physical mapping table starts at this address, read-only.
*/
#define HYPERVISOR_VIRT_START (0xFC000000UL)
#ifdef CONFIG_X86_PAE
# define HYPERVISOR_VIRT_START (0xF5800000UL)
#else
# define HYPERVISOR_VIRT_START (0xFC000000UL)
#endif
#ifndef machine_to_phys_mapping
#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
#endif
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.