ia64/xen-unstable
changeset 9759:7a9a00c51588
[IA64] introduce dom0vp hypercalls
implement dom0vp hypercall.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
implement dom0vp hypercall.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author | awilliam@ldap.hp.com |
---|---|
date | Tue Apr 25 13:56:30 2006 -0600 (2006-04-25) |
parents | ae0d41bd3bba |
children | 8a2b2b45e237 |
files | xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/hypercall.c xen/include/asm-ia64/domain.h xen/include/public/arch-ia64.h |
line diff
1.1 --- a/xen/arch/ia64/xen/dom0_ops.c Tue Apr 25 13:48:02 2006 -0600 1.2 +++ b/xen/arch/ia64/xen/dom0_ops.c Tue Apr 25 13:56:30 2006 -0600 1.3 @@ -236,6 +236,55 @@ long arch_do_dom0_op(dom0_op_t *op, GUES 1.4 return ret; 1.5 } 1.6 1.7 +#ifdef CONFIG_XEN_IA64_DOM0_VP 1.8 +unsigned long 1.9 +do_dom0vp_op(unsigned long cmd, 1.10 + unsigned long arg0, unsigned long arg1, unsigned long arg2, 1.11 + unsigned long arg3) 1.12 +{ 1.13 + unsigned long ret = 0; 1.14 + struct domain *d = current->domain; 1.15 + 1.16 + switch (cmd) { 1.17 + case IA64_DOM0VP_ioremap: 1.18 + ret = assign_domain_mmio_page(d, arg0, arg1); 1.19 + break; 1.20 + case IA64_DOM0VP_phystomach: 1.21 + ret = ____lookup_domain_mpa(d, arg0 << PAGE_SHIFT); 1.22 + if (ret == INVALID_MFN) { 1.23 + DPRINTK("%s:%d INVALID_MFN ret: 0x%lx\n", __func__, __LINE__, ret); 1.24 + } else { 1.25 + ret = (ret & _PFN_MASK) >> PAGE_SHIFT;//XXX pte_pfn() 1.26 + } 1.27 + break; 1.28 + case IA64_DOM0VP_machtophys: 1.29 + if (max_page <= arg0) { 1.30 + ret = INVALID_M2P_ENTRY; 1.31 + break; 1.32 + } 1.33 + ret = get_gpfn_from_mfn(arg0); 1.34 + break; 1.35 + case IA64_DOM0VP_populate_physmap: 1.36 + ret = dom0vp_populate_physmap(d, arg0, 1.37 + (unsigned int)arg1, (unsigned int)arg2); 1.38 + break; 1.39 + case IA64_DOM0VP_zap_physmap: 1.40 + ret = dom0vp_zap_physmap(d, arg0, (unsigned int)arg1); 1.41 + break; 1.42 + case IA64_DOM0VP_add_physmap: 1.43 + ret = dom0vp_add_physmap(d, arg0, arg1, (unsigned int)arg2, 1.44 + (domid_t)arg3); 1.45 + break; 1.46 + default: 1.47 + ret = -1; 1.48 + printf("unknown dom0_vp_op 0x%lx\n", cmd); 1.49 + break; 1.50 + } 1.51 + 1.52 + return ret; 1.53 +} 1.54 +#endif 1.55 + 1.56 /* 1.57 * Local variables: 1.58 * mode: C
2.1 --- a/xen/arch/ia64/xen/domain.c Tue Apr 25 13:48:02 2006 -0600 2.2 +++ b/xen/arch/ia64/xen/domain.c Tue Apr 25 13:56:30 2006 -0600 2.3 @@ -887,6 +887,151 @@ unsigned long lookup_domain_mpa(struct d 2.4 return 0; 2.5 } 2.6 2.7 +#ifdef CONFIG_XEN_IA64_DOM0_VP 2.8 +//XXX SMP 2.9 +unsigned long 2.10 +dom0vp_populate_physmap(struct domain *d, unsigned long gpfn, 2.11 + unsigned int extent_order, unsigned int address_bits) 2.12 +{ 2.13 + unsigned long ret = 0; 2.14 + int flags = 0; 2.15 + unsigned long mpaddr = gpfn << PAGE_SHIFT; 2.16 + unsigned long extent_size = 1UL << extent_order; 2.17 + unsigned long offset; 2.18 + struct page_info* page; 2.19 + unsigned long physaddr; 2.20 + 2.21 + if (extent_order > 0 && !multipage_allocation_permitted(d)) { 2.22 + ret = -EINVAL; 2.23 + goto out; 2.24 + } 2.25 + 2.26 + if (gpfn + (1 << extent_order) < gpfn) { 2.27 + ret = -EINVAL; 2.28 + goto out; 2.29 + } 2.30 + if (gpfn > d->max_pages || gpfn + (1 << extent_order) > d->max_pages) { 2.31 + ret = -EINVAL; 2.32 + goto out; 2.33 + } 2.34 + if ((extent_size << PAGE_SHIFT) < extent_size) { 2.35 + ret = -EINVAL; 2.36 + goto out; 2.37 + } 2.38 + 2.39 + //XXX check address_bits and set flags = ALLOC_DOM_DMA if needed 2.40 + 2.41 + // check the rage is not populated yet. 2.42 + //XXX loop optimization 2.43 + for (offset = 0; offset < extent_size << PAGE_SHIFT; offset += PAGE_SIZE) { 2.44 + if (____lookup_domain_mpa(d, mpaddr + offset) != INVALID_MFN) { 2.45 + ret = -EBUSY; 2.46 + goto out; 2.47 + } 2.48 + } 2.49 + 2.50 + page = alloc_domheap_pages(d, extent_order, flags); 2.51 + if (page == NULL) { 2.52 + ret = -ENOMEM; 2.53 + DPRINTK("Could not allocate order=%d extent: id=%d flags=%x\n", 2.54 + extent_order, d->domain_id, flags); 2.55 + goto out; 2.56 + } 2.57 + 2.58 + //XXX loop optimization 2.59 + physaddr = page_to_maddr(page); 2.60 + for (offset = 0; offset < extent_size << PAGE_SHIFT; offset += PAGE_SIZE) { 2.61 + assign_domain_page(d, mpaddr + offset, physaddr + offset); 2.62 + } 2.63 + 2.64 +out: 2.65 + return ret; 2.66 +} 2.67 + 2.68 +//XXX SMP 2.69 +unsigned long 2.70 +dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, 2.71 + unsigned int extent_order) 2.72 +{ 2.73 + unsigned long ret = 0; 2.74 + if (extent_order != 0) { 2.75 + //XXX 2.76 + ret = -ENOSYS; 2.77 + goto out; 2.78 + } 2.79 + 2.80 + zap_domain_page_one(d, gpfn << PAGE_SHIFT); 2.81 + 2.82 +out: 2.83 + return ret; 2.84 +} 2.85 + 2.86 +static void 2.87 +assign_domain_page_replace(struct domain *d, unsigned long mpaddr, 2.88 + unsigned long mfn, unsigned int flags) 2.89 +{ 2.90 + struct mm_struct *mm = d->arch.mm; 2.91 + pte_t* pte; 2.92 + pte_t old_pte; 2.93 + 2.94 + pte = lookup_alloc_domain_pte(d, mpaddr); 2.95 + 2.96 + // update pte 2.97 + old_pte = ptep_get_and_clear(mm, mpaddr, pte); 2.98 + set_pte(pte, pfn_pte(mfn, 2.99 + __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX))); 2.100 + if (!pte_none(old_pte)) { 2.101 + unsigned long old_mfn; 2.102 + struct page_info* old_page; 2.103 + 2.104 + // XXX should previous underlying page be removed? 2.105 + // or should error be returned because it is a due to a domain? 2.106 + old_mfn = pte_pfn(old_pte);//XXX 2.107 + old_page = mfn_to_page(old_mfn); 2.108 + 2.109 + if (page_get_owner(old_page) == d) { 2.110 + BUG_ON(get_gpfn_from_mfn(old_mfn) != (mpaddr >> PAGE_SHIFT)); 2.111 + set_gpfn_from_mfn(old_mfn, INVALID_M2P_ENTRY); 2.112 + } 2.113 + 2.114 + domain_page_flush(d, mpaddr, old_mfn, mfn); 2.115 + 2.116 + put_page(old_page); 2.117 + } else { 2.118 + BUG_ON(page_get_owner(mfn_to_page(mfn)) == d && 2.119 + get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY); 2.120 + } 2.121 +} 2.122 + 2.123 +unsigned long 2.124 +dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, 2.125 + unsigned int flags, domid_t domid) 2.126 +{ 2.127 + int error = 0; 2.128 + 2.129 + struct domain* rd; 2.130 + rd = find_domain_by_id(domid); 2.131 + if (unlikely(rd == NULL)) { 2.132 + error = -EINVAL; 2.133 + goto out0; 2.134 + } 2.135 + if (unlikely(rd == d)) { 2.136 + error = -EINVAL; 2.137 + goto out1; 2.138 + } 2.139 + if (unlikely(get_page(mfn_to_page(mfn), rd) == 0)) { 2.140 + error = -EINVAL; 2.141 + goto out1; 2.142 + } 2.143 + 2.144 + assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, 0/* flags:XXX */); 2.145 +out1: 2.146 + put_domain(rd); 2.147 +out0: 2.148 + return error; 2.149 +} 2.150 +#endif 2.151 + 2.152 /* Flush cache of domain d. */ 2.153 void domain_cache_flush (struct domain *d, int sync_only) 2.154 {
3.1 --- a/xen/arch/ia64/xen/hypercall.c Tue Apr 25 13:48:02 2006 -0600 3.2 +++ b/xen/arch/ia64/xen/hypercall.c Tue Apr 25 13:56:30 2006 -0600 3.3 @@ -124,6 +124,12 @@ xen_hypercall (struct pt_regs *regs) 3.4 guest_handle_from_ptr(regs->r15, void)); 3.5 break; 3.6 3.7 +#ifdef CONFIG_XEN_IA64_DOM0_VP 3.8 + case __HYPERVISOR_ia64_dom0vp_op: 3.9 + regs->r8 = do_dom0vp_op(regs->r14, regs->r15, regs->r16, 3.10 + regs->r17, regs->r18); 3.11 + break; 3.12 +#endif 3.13 default: 3.14 printf("unknown xen hypercall %lx\n", regs->r2); 3.15 regs->r8 = do_ni_hypercall();
4.1 --- a/xen/include/asm-ia64/domain.h Tue Apr 25 13:48:02 2006 -0600 4.2 +++ b/xen/include/asm-ia64/domain.h Tue Apr 25 13:56:30 2006 -0600 4.3 @@ -169,6 +169,10 @@ void assign_domain_io_page(struct domain 4.4 #ifdef CONFIG_XEN_IA64_DOM0_VP 4.5 unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size); 4.6 unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size); 4.7 +unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3); 4.8 +unsigned long dom0vp_populate_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order, unsigned int address_bits); 4.9 +unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order); 4.10 +unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned int flags, domid_t domid); 4.11 #endif 4.12 4.13 #include <asm/uaccess.h> /* for KERNEL_DS */
5.1 --- a/xen/include/public/arch-ia64.h Tue Apr 25 13:48:02 2006 -0600 5.2 +++ b/xen/include/public/arch-ia64.h Tue Apr 25 13:56:30 2006 -0600 5.3 @@ -326,6 +326,41 @@ typedef struct vcpu_guest_context { 5.4 } vcpu_guest_context_t; 5.5 DEFINE_GUEST_HANDLE(vcpu_guest_context_t); 5.6 5.7 +// dom0 vp op 5.8 +#define __HYPERVISOR_ia64_dom0vp_op 256 // XXX sufficient large 5.9 + // TODO 5.10 + // arch specific hypercall 5.11 + // number conversion 5.12 +#define IA64_DOM0VP_ioremap 0 // map io space in machine 5.13 + // address to dom0 physical 5.14 + // address space. 5.15 + // currently physical 5.16 + // assignedg address equals to 5.17 + // machine address 5.18 +#define IA64_DOM0VP_phystomach 1 // convert a pseudo physical 5.19 + // page frame number 5.20 + // to the corresponding 5.21 + // machine page frame number. 5.22 + // if no page is assigned, 5.23 + // INVALID_MFN or GPFN_INV_MASK 5.24 + // is returned depending on 5.25 + // domain's non-vti/vti mode. 5.26 +#define IA64_DOM0VP_machtophys 3 // convert a machine page 5.27 + // frame number 5.28 + // to the corresponding 5.29 + // pseudo physical page frame 5.30 + // number of the caller domain 5.31 +#define IA64_DOM0VP_populate_physmap 16 // allocate machine-contigusous 5.32 + // memory region and 5.33 + // map it to pseudo physical 5.34 + // address 5.35 +#define IA64_DOM0VP_zap_physmap 17 // unmap and free pages 5.36 + // contained in the specified 5.37 + // pseudo physical region 5.38 +#define IA64_DOM0VP_add_physmap 18 // assigne machine page frane 5.39 + // to dom0's pseudo physical 5.40 + // address space. 5.41 + 5.42 #endif /* !__ASSEMBLY__ */ 5.43 5.44 #endif /* __HYPERVISOR_IF_IA64_H__ */