#include <xen/interface/memory.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
+
#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+
+#include <asm/pgtable.h>
+
struct start_info _xen_start_info = { .flags = (SIF_INITDOMAIN|SIF_PRIVILEGED) };
struct start_info *xen_start_info = &_xen_start_info;
EXPORT_SYMBOL_GPL(xen_start_info);
int xen_platform_pci_unplug;
EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
+#define FOREIGN_MAP_BUFFER 0x90000000UL
+#define FOREIGN_MAP_BUFFER_SIZE 0x10000000UL
+struct resource foreign_map_resource = {
+ .start = FOREIGN_MAP_BUFFER,
+ .end = FOREIGN_MAP_BUFFER + FOREIGN_MAP_BUFFER_SIZE,
+ .name = "Xen foreign map buffer",
+ .flags = 0,
+};
+
+static unsigned long foreign_map_buffer_pfn = FOREIGN_MAP_BUFFER >> PAGE_SHIFT;
+
/* TODO */
+
+struct remap_data {
+ struct mm_struct *mm;
+ unsigned long mfn;
+ pgprot_t prot;
+};
+
+static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
+ unsigned long addr, void *data)
+{
+ struct remap_data *rmd = data;
+/* pte_mkspecial(); */
+ pte_t pte = pfn_pte(rmd->mfn, rmd->prot);
+
+ if ( rmd->mfn < 0x90010 )
+ printk(KERN_CRIT "%s: ptep %p addr %#lx => %#x / %#lx\n",
+ __func__, ptep, addr, pte_val(pte), rmd->mfn);
+
+ set_pte_at(rmd->mm, addr, ptep, pte);
+
+ rmd->mfn++;
+ return 0;
+}
+
+
int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
unsigned long addr,
unsigned long mfn, int nr,
pgprot_t prot, unsigned domid)
{
- return -ENOSYS;
+ int i, rc = 0;
+ struct remap_data rmd = {
+ .mm = vma->vm_mm,
+ .prot = prot,
+ };
+ struct xen_add_to_physmap xatp = {
+ .domid = DOMID_SELF,
+ .space = XENMAPSPACE_gmfn_foreign,
+
+ .foreign_domid = domid,
+ };
+
+ if ( foreign_map_buffer_pfn + nr > ((FOREIGN_MAP_BUFFER + FOREIGN_MAP_BUFFER_SIZE)>>PAGE_SHIFT) ) {
+ printk(KERN_CRIT "RAM out of foreign map buffers...\n");
+ return -EBUSY;
+ }
+
+ //printk(KERN_CRIT "%s: vma=%p addr=%#lx mfn=%#lx nr=%#x prot=%#x domid=%d\n",
+ // __func__, vma, addr, mfn, nr, prot, domid);
+ //printk(KERN_CRIT "%s: Buffer PFN %#lx\n", __func__, foreign_map_buffer_pfn);
+
+ for (i=0; i<nr; i++) {
+ xatp.idx = mfn + i;
+ xatp.gpfn = foreign_map_buffer_pfn + i;
+ //printk(KERN_CRIT "mapping dom%d gpfn %#lx -> pfn %#"PRI_xen_pfn"\n",
+ // domid, xatp.idx, xatp.gpfn);
+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
+ if (rc != 0) {
+ printk(KERN_CRIT
+ "foreign map add_to_physmap failed, err=%d\n", rc);
+ goto out;
+ }
+ }
+
+ //printk(KERN_CRIT "%s: apply_to_page_range %#lx %#lx %#lx\n",
+ // __func__, addr, foreign_map_buffer_pfn << PAGE_SHIFT, (unsigned long)nr << PAGE_SHIFT);
+
+ rmd.mfn = foreign_map_buffer_pfn;
+ rc = apply_to_page_range(vma->vm_mm,
+ addr, //vma->vm_start, //foreign_map_buffer_pfn << PAGE_SHIFT,
+ (unsigned long)nr << PAGE_SHIFT,
+ remap_area_mfn_pte_fn, &rmd);
+ if (rc != 0) {
+ printk(KERN_CRIT "apply_to_page_range failed rc=%d\n", rc);
+ goto out;
+ }
+
+ //printk(KERN_CRIT "%s: success\n", __func__);
+ foreign_map_buffer_pfn += nr;
+out:
+ return rc;
}
EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/seq_file.h>
+#include <linux/resource.h>
+#include <linux/ioport.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
LIST_HEAD(pagelist);
struct mmap_mfn_state state;
- if (!xen_initial_domain())
- return -EPERM;
+ //if (!xen_initial_domain())
+ // return -EPERM;
if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
return -EFAULT;
LIST_HEAD(pagelist);
struct mmap_batch_state state;
- if (!xen_initial_domain())
- return -EPERM;
+ //if (!xen_initial_domain())
+ // return -EPERM;
if (copy_from_user(&m, udata, sizeof(m)))
return -EFAULT;
}
#ifndef HAVE_ARCH_PRIVCMD_MMAP
+static void privcmd_close(struct vm_area_struct *vma)
+{
+ //printk(KERN_CRIT "should unmap vma %p\n", vma);
+}
+
static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
- printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
+ printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, virt=%p\n",
vma, vma->vm_start, vma->vm_end,
vmf->pgoff, vmf->virtual_address);
+ show_pte(vma->vm_mm, vmf->virtual_address);
+ show_pte(vma->vm_mm, vmf->virtual_address-PAGE_SIZE);
return VM_FAULT_SIGBUS;
}
static struct vm_operations_struct privcmd_vm_ops = {
- .fault = privcmd_fault
+ .fault = privcmd_fault,
+ .close = privcmd_close,
};
static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
{
+ //printk(KERN_CRIT "privcmd_mmap\n");
+
/* Unsupported for auto-translate guests. */
if (xen_feature(XENFEAT_auto_translated_physmap))
+ {
+ printk(KERN_CRIT "privcmd_mmap -- no auto translated..\n");
return -ENOSYS;
+ }
/* DONTCOPY is essential for Xen because copy_page_range doesn't know
* how to recreate these mappings */
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/magic.h>
+#include <linux/ioport.h>
#include <xen/xen.h>
.llseek = default_llseek,
};
+extern struct resource foreign_map_resource;
+
static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
{
static struct tree_descr xenfs_files[] = {
&xsd_kva_file_ops, NULL, S_IRUSR|S_IWUSR);
xenfs_create_file(sb, sb->s_root, "xsd_port",
&xsd_port_file_ops, NULL, S_IRUSR|S_IWUSR);
+ rc = request_resource(&iomem_resource, &foreign_map_resource);
+ if (rc < 0)
+ printk(KERN_ERR "failed to register foreign map resource\n");
+ rc = 0; /* ignore */
}
return rc;