aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/mmu.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-02-04 17:46:34 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2010-06-07 14:32:33 -0400
commitc0011dbfce69467b23b08fb4a64c39a409a935fb (patch)
tree47ecf9ee630f58d49edd2fd18fdc0159eb486392 /arch/x86/xen/mmu.c
parente40152ee1e1c7a63f4777791863215e3faa37a86 (diff)
xen: use _PAGE_IOMAP in ioremap to do machine mappings
In a Xen domain, ioremap operates on machine addresses, not pseudo-physical addresses. We use _PAGE_IOMAP to determine whether a mapping is intended for machine addresses. [ Impact: allow Xen domain to map real hardware ] Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86/xen/mmu.c')
-rw-r--r--arch/x86/xen/mmu.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 914f04695ce5..a4dea9df0cc0 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -56,9 +56,11 @@
56#include <asm/xen/hypercall.h> 56#include <asm/xen/hypercall.h>
57#include <asm/xen/hypervisor.h> 57#include <asm/xen/hypervisor.h>
58 58
59#include <xen/xen.h>
59#include <xen/page.h> 60#include <xen/page.h>
60#include <xen/interface/xen.h> 61#include <xen/interface/xen.h>
61#include <xen/interface/version.h> 62#include <xen/interface/version.h>
63#include <xen/interface/memory.h>
62#include <xen/hvc-console.h> 64#include <xen/hvc-console.h>
63 65
64#include "multicalls.h" 66#include "multicalls.h"
@@ -377,6 +379,28 @@ static bool xen_page_pinned(void *ptr)
377 return PagePinned(page); 379 return PagePinned(page);
378} 380}
379 381
382static bool xen_iomap_pte(pte_t pte)
383{
384 return xen_initial_domain() && (pte_flags(pte) & _PAGE_IOMAP);
385}
386
387static void xen_set_iomap_pte(pte_t *ptep, pte_t pteval)
388{
389 struct multicall_space mcs;
390 struct mmu_update *u;
391
392 mcs = xen_mc_entry(sizeof(*u));
393 u = mcs.args;
394
395 /* ptep might be kmapped when using 32-bit HIGHPTE */
396 u->ptr = arbitrary_virt_to_machine(ptep).maddr;
397 u->val = pte_val_ma(pteval);
398
399 MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_IO);
400
401 xen_mc_issue(PARAVIRT_LAZY_MMU);
402}
403
380static void xen_extend_mmu_update(const struct mmu_update *update) 404static void xen_extend_mmu_update(const struct mmu_update *update)
381{ 405{
382 struct multicall_space mcs; 406 struct multicall_space mcs;
@@ -453,6 +477,11 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
453void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, 477void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
454 pte_t *ptep, pte_t pteval) 478 pte_t *ptep, pte_t pteval)
455{ 479{
480 if (xen_iomap_pte(pteval)) {
481 xen_set_iomap_pte(ptep, pteval);
482 goto out;
483 }
484
456 ADD_STATS(set_pte_at, 1); 485 ADD_STATS(set_pte_at, 1);
457// ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep)); 486// ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep));
458 ADD_STATS(set_pte_at_current, mm == current->mm); 487 ADD_STATS(set_pte_at_current, mm == current->mm);
@@ -523,8 +552,25 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
523 return val; 552 return val;
524} 553}
525 554
555static pteval_t iomap_pte(pteval_t val)
556{
557 if (val & _PAGE_PRESENT) {
558 unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
559 pteval_t flags = val & PTE_FLAGS_MASK;
560
561 /* We assume the pte frame number is a MFN, so
562 just use it as-is. */
563 val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
564 }
565
566 return val;
567}
568
526pteval_t xen_pte_val(pte_t pte) 569pteval_t xen_pte_val(pte_t pte)
527{ 570{
571 if (xen_initial_domain() && (pte.pte & _PAGE_IOMAP))
572 return pte.pte;
573
528 return pte_mfn_to_pfn(pte.pte); 574 return pte_mfn_to_pfn(pte.pte);
529} 575}
530PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val); 576PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val);
@@ -537,7 +583,11 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_pgd_val);
537 583
538pte_t xen_make_pte(pteval_t pte) 584pte_t xen_make_pte(pteval_t pte)
539{ 585{
540 pte = pte_pfn_to_mfn(pte); 586 if (unlikely(xen_initial_domain() && (pte & _PAGE_IOMAP)))
587 pte = iomap_pte(pte);
588 else
589 pte = pte_pfn_to_mfn(pte);
590
541 return native_make_pte(pte); 591 return native_make_pte(pte);
542} 592}
543PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); 593PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte);
@@ -593,6 +643,11 @@ void xen_set_pud(pud_t *ptr, pud_t val)
593 643
594void xen_set_pte(pte_t *ptep, pte_t pte) 644void xen_set_pte(pte_t *ptep, pte_t pte)
595{ 645{
646 if (xen_iomap_pte(pte)) {
647 xen_set_iomap_pte(ptep, pte);
648 return;
649 }
650
596 ADD_STATS(pte_update, 1); 651 ADD_STATS(pte_update, 1);
597// ADD_STATS(pte_update_pinned, xen_page_pinned(ptep)); 652// ADD_STATS(pte_update_pinned, xen_page_pinned(ptep));
598 ADD_STATS(pte_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); 653 ADD_STATS(pte_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU);
@@ -609,6 +664,11 @@ void xen_set_pte(pte_t *ptep, pte_t pte)
609#ifdef CONFIG_X86_PAE 664#ifdef CONFIG_X86_PAE
610void xen_set_pte_atomic(pte_t *ptep, pte_t pte) 665void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
611{ 666{
667 if (xen_iomap_pte(pte)) {
668 xen_set_iomap_pte(ptep, pte);
669 return;
670 }
671
612 set_64bit((u64 *)ptep, native_pte_val(pte)); 672 set_64bit((u64 *)ptep, native_pte_val(pte));
613} 673}
614 674
@@ -1811,9 +1871,16 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
1811 pte = pfn_pte(phys, prot); 1871 pte = pfn_pte(phys, prot);
1812 break; 1872 break;
1813 1873
1814 default: 1874 case FIX_PARAVIRT_BOOTMAP:
1875 /* This is an MFN, but it isn't an IO mapping from the
1876 IO domain */
1815 pte = mfn_pte(phys, prot); 1877 pte = mfn_pte(phys, prot);
1816 break; 1878 break;
1879
1880 default:
1881 /* By default, set_fixmap is used for hardware mappings */
1882 pte = mfn_pte(phys, __pgprot(pgprot_val(prot) | _PAGE_IOMAP));
1883 break;
1817 } 1884 }
1818 1885
1819 __native_set_fixmap(idx, pte); 1886 __native_set_fixmap(idx, pte);