mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.913 (40ab4ea8vu84ako0LR_rQN0fDuznVw)
Fix the mmu_update hypercall interface.
This commit is contained in:
1 parent
c9cfbb3322
commit
74a3bae43b
11 files changed
+62
-80
No files matched your search
@@ -50,13 +50,15 @@ static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req, int count)
|
||||
static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req,
|
||||
int count,
|
||||
int *success_count)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_mmu_update),
|
||||
"b" (req), "c" (count) : "memory" );
|
||||
"b" (req), "c" (count), "d" (success_count) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -323,7 +323,8 @@ static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
|
||||
|
||||
hypercall.op = __HYPERVISOR_mmu_update;
|
||||
hypercall.arg[0] = (unsigned long)mmu->updates;
|
||||
hypercall.arg[1] = (unsigned long)&(mmu->idx);
|
||||
hypercall.arg[1] = (unsigned long)mmu->idx;
|
||||
hypercall.arg[2] = 0;
|
||||
|
||||
if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
|
||||
{
|
||||
|
||||
+3
-9
@@ -988,9 +988,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
|
||||
}
|
||||
|
||||
|
||||
int do_mmu_update(mmu_update_t *ureqs, int * p_count)
|
||||
int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
|
||||
{
|
||||
int count;
|
||||
mmu_update_t req;
|
||||
unsigned long va = 0, deferred_ops, pfn, prev_pfn = 0;
|
||||
struct pfn_info *page;
|
||||
@@ -999,11 +998,6 @@ int do_mmu_update(mmu_update_t *ureqs, int * p_count)
|
||||
unsigned long prev_spfn = 0;
|
||||
l1_pgentry_t *prev_spl1e = 0;
|
||||
|
||||
if ( unlikely( get_user(count, p_count) ) )
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
perfc_incrc(calls_to_mmu_update);
|
||||
perfc_addc(num_page_updates, count);
|
||||
|
||||
@@ -1160,8 +1154,8 @@ int do_mmu_update(mmu_update_t *ureqs, int * p_count)
|
||||
percpu_info[cpu].gps = percpu_info[cpu].pts = NULL;
|
||||
}
|
||||
|
||||
if ( unlikely(rc) )
|
||||
put_user( count, p_count );
|
||||
if ( unlikely(success_count != NULL) )
|
||||
put_user(count, success_count);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ int check_descriptor(unsigned long a, unsigned long b);
|
||||
#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
|
||||
|
||||
/* Part of the domain API. */
|
||||
int do_mmu_update(mmu_update_t *updates, int *count);
|
||||
int do_mmu_update(mmu_update_t *updates, int count, int *success_count);
|
||||
|
||||
#define DEFAULT_GDT_ENTRIES ((LAST_RESERVED_GDT_ENTRY*8)+7)
|
||||
#define DEFAULT_GDT_ADDRESS ((unsigned long)gdt_table)
|
||||
|
||||
@@ -89,18 +89,18 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
|
||||
return -EFAULT;
|
||||
|
||||
for (j=0;j<n;j++)
|
||||
for ( j = 0; j < n; j++ )
|
||||
{
|
||||
struct vm_area_struct *vma =
|
||||
find_vma( current->mm, msg[j].va );
|
||||
|
||||
if (!vma)
|
||||
if ( !vma )
|
||||
return -EINVAL;
|
||||
|
||||
if (msg[j].va > PAGE_OFFSET)
|
||||
if ( msg[j].va > PAGE_OFFSET )
|
||||
return -EINVAL;
|
||||
|
||||
if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end)
|
||||
if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
|
||||
return -EINVAL;
|
||||
|
||||
if ( (rc = direct_remap_area_pages(vma->vm_mm,
|
||||
@@ -108,7 +108,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
msg[j].mfn<<PAGE_SHIFT,
|
||||
msg[j].npages<<PAGE_SHIFT,
|
||||
vma->vm_page_prot,
|
||||
mmapcmd.dom)) <0)
|
||||
mmapcmd.dom)) < 0 )
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -131,21 +131,15 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
vma = find_vma( current->mm, m.addr );
|
||||
|
||||
if (!vma)
|
||||
if ( !vma )
|
||||
{ ret = -EINVAL; goto batch_err; }
|
||||
|
||||
if (m.addr > PAGE_OFFSET)
|
||||
if ( m.addr > PAGE_OFFSET )
|
||||
{ ret = -EFAULT; goto batch_err; }
|
||||
|
||||
if (m.addr + (m.num<<PAGE_SHIFT) > vma->vm_end)
|
||||
if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end )
|
||||
{ ret = -EFAULT; goto batch_err; }
|
||||
|
||||
// everything fits inside the vma
|
||||
|
||||
//printk("direct_r_a_p sx=%ld address=%lx macaddr=%lx dom=%lld\n",size,address,machine_addr,domid);
|
||||
// memset( u, 0, sizeof(mmu_update_t)*MAX_DIRECTMAP_MMU_QUEUE );// XXX
|
||||
|
||||
|
||||
if ( m.dom != 0 )
|
||||
{
|
||||
u[0].val = (unsigned long)(m.dom<<16) & ~0xFFFFUL;
|
||||
@@ -165,35 +159,28 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
p = m.arr;
|
||||
addr = m.addr;
|
||||
//printk("BATCH: arr=%p addr=%lx num=%d u=%p,w=%p\n",p,addr,m.num,u,w);
|
||||
for (i=0; i<m.num; i++, addr+=PAGE_SIZE, p++)
|
||||
for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ )
|
||||
{
|
||||
unsigned int count;
|
||||
if ( get_user(mfn, p) ) return -EFAULT;
|
||||
|
||||
v->val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot) |
|
||||
_PAGE_IO;
|
||||
|
||||
__direct_remap_area_pages( vma->vm_mm,
|
||||
addr,
|
||||
PAGE_SIZE,
|
||||
v);
|
||||
v++;
|
||||
count = v-u;
|
||||
//printk("Q i=%d mfn=%x co=%d v=%p : %lx %lx\n",i,mfn,count,v, w->val,w->ptr);
|
||||
__direct_remap_area_pages(vma->vm_mm,
|
||||
addr,
|
||||
PAGE_SIZE,
|
||||
v);
|
||||
|
||||
if ( HYPERVISOR_mmu_update(u, &count) < 0 )
|
||||
{
|
||||
//printk("Fail %d->%d mfn=%lx\n",v-u,count, w->val);
|
||||
if ( unlikely(HYPERVISOR_mmu_update(u, v - u + 1, NULL) < 0) )
|
||||
put_user( 0xe0000000 | mfn, p );
|
||||
}
|
||||
v=w;
|
||||
|
||||
v = w;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
batch_err:
|
||||
printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%lx %lx-%lx\n",
|
||||
printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n",
|
||||
ret, vma, m.addr, m.num, m.arr, vma->vm_start, vma->vm_end);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -231,6 +231,7 @@ static void net_rx_action(unsigned long unused)
|
||||
mcl[1].op = __HYPERVISOR_mmu_update;
|
||||
mcl[1].args[0] = (unsigned long)mmu;
|
||||
mcl[1].args[1] = 4;
|
||||
mcl[1].args[2] = 0;
|
||||
|
||||
mmu += 4;
|
||||
mcl += 2;
|
||||
|
||||
@@ -384,6 +384,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
mcl->op = __HYPERVISOR_mmu_update;
|
||||
mcl->args[0] = (unsigned long)rx_mmu;
|
||||
mcl->args[1] = mmu - rx_mmu;
|
||||
mcl->args[2] = 0;
|
||||
mcl++;
|
||||
(void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
}
|
||||
|
||||
@@ -317,12 +317,11 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
|
||||
__asm__ __volatile__ ( "sldt %0" : "=r" (ldt) );
|
||||
if ( ldt == 0 )
|
||||
{
|
||||
int count = 1;
|
||||
mmu_update_t u;
|
||||
u.ptr = MMU_EXTENDED_COMMAND;
|
||||
u.ptr |= (unsigned long)&default_ldt[0];
|
||||
u.val = MMUEXT_SET_LDT | (5 << MMUEXT_CMD_SHIFT);
|
||||
if ( unlikely(HYPERVISOR_mmu_update(&u, &count) < 0) )
|
||||
if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL) < 0) )
|
||||
{
|
||||
show_trace(NULL);
|
||||
panic("Failed to install default LDT");
|
||||
@@ -644,7 +643,7 @@ void __init trap_init(void)
|
||||
* don't set them to safe values on entry to the kernel). At *any* point Xen
|
||||
* may be entered due to a hardware interrupt --- on exit from Xen an invalid
|
||||
* FS/GS will cause our failsafe_callback to be executed. This could occur,
|
||||
* for example, while the mmmu_update_queue is in an inconsistent state. This
|
||||
* for example, while the mmu_update_queue is in an inconsistent state. This
|
||||
* is disastrous because the normal page-fault handler touches the update
|
||||
* queue!
|
||||
*
|
||||
|
||||
@@ -40,13 +40,12 @@ static void DEBUG_allow_pt_reads(void)
|
||||
int i;
|
||||
for ( i = idx-1; i >= 0; i-- )
|
||||
{
|
||||
int count = 1;
|
||||
pte = update_debug_queue[i].ptep;
|
||||
if ( pte == NULL ) continue;
|
||||
update_debug_queue[i].ptep = NULL;
|
||||
update.ptr = virt_to_machine(pte);
|
||||
update.val = update_debug_queue[i].pteval;
|
||||
HYPERVISOR_mmu_update(&update, &count);
|
||||
HYPERVISOR_mmu_update(&update, 1, NULL);
|
||||
}
|
||||
}
|
||||
static void DEBUG_disallow_pt_read(unsigned long va)
|
||||
@@ -55,7 +54,6 @@ static void DEBUG_disallow_pt_read(unsigned long va)
|
||||
pmd_t *pmd;
|
||||
pgd_t *pgd;
|
||||
unsigned long pteval;
|
||||
int count = 1;
|
||||
/*
|
||||
* We may fault because of an already outstanding update.
|
||||
* That's okay -- it'll get fixed up in the fault handler.
|
||||
@@ -67,7 +65,7 @@ static void DEBUG_disallow_pt_read(unsigned long va)
|
||||
update.ptr = virt_to_machine(pte);
|
||||
pteval = *(unsigned long *)pte;
|
||||
update.val = pteval & ~_PAGE_PRESENT;
|
||||
HYPERVISOR_mmu_update(&update, &count);
|
||||
HYPERVISOR_mmu_update(&update, 1, NULL);
|
||||
update_debug_queue[idx].ptep = pte;
|
||||
update_debug_queue[idx].pteval = pteval;
|
||||
}
|
||||
@@ -103,9 +101,10 @@ void MULTICALL_flush_page_update_queue(void)
|
||||
#endif
|
||||
idx = 0;
|
||||
wmb(); /* Make sure index is cleared first to avoid double updates. */
|
||||
queue_multicall2(__HYPERVISOR_mmu_update,
|
||||
queue_multicall3(__HYPERVISOR_mmu_update,
|
||||
(unsigned long)update_queue,
|
||||
&_idx);
|
||||
(unsigned long)_idx,
|
||||
(unsigned long)NULL);
|
||||
}
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
@@ -121,7 +120,7 @@ static inline void __flush_page_update_queue(void)
|
||||
#endif
|
||||
idx = 0;
|
||||
wmb(); /* Make sure index is cleared first to avoid double updates. */
|
||||
if ( unlikely(HYPERVISOR_mmu_update(update_queue, &_idx) < 0) )
|
||||
if ( unlikely(HYPERVISOR_mmu_update(update_queue, _idx, NULL) < 0) )
|
||||
panic("Failed to execute MMU updates");
|
||||
}
|
||||
|
||||
|
||||
@@ -42,18 +42,11 @@ static inline void direct_remap_area_pte(pte_t *pte,
|
||||
BUG();
|
||||
|
||||
do {
|
||||
#if 0 // XXX
|
||||
if (!pte_none(*pte)) {
|
||||
printk("direct_remap_area_pte: page already exists\n");
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
(*v)->ptr = virt_to_machine(pte);
|
||||
(*v)++;
|
||||
address += PAGE_SIZE;
|
||||
pte++;
|
||||
} while (address && (address < end));
|
||||
return ;
|
||||
}
|
||||
|
||||
static inline int direct_remap_area_pmd(struct mm_struct *mm,
|
||||
@@ -71,7 +64,7 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm,
|
||||
if (address >= end)
|
||||
BUG();
|
||||
do {
|
||||
pte_t * pte = pte_alloc(mm, pmd, address);
|
||||
pte_t *pte = pte_alloc(mm, pmd, address);
|
||||
if (!pte)
|
||||
return -ENOMEM;
|
||||
direct_remap_area_pte(pte, address, end - address, v);
|
||||
@@ -117,7 +110,7 @@ int direct_remap_area_pages(struct mm_struct *mm,
|
||||
pgprot_t prot,
|
||||
domid_t domid)
|
||||
{
|
||||
int i, count;
|
||||
int i;
|
||||
unsigned long start_address;
|
||||
#define MAX_DIRECTMAP_MMU_QUEUE 130
|
||||
mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v;
|
||||
@@ -141,39 +134,42 @@ int direct_remap_area_pages(struct mm_struct *mm,
|
||||
|
||||
start_address = address;
|
||||
|
||||
for(i=0; i<size;
|
||||
i+=PAGE_SIZE, machine_addr+=PAGE_SIZE, address+=PAGE_SIZE, v++)
|
||||
for( i = 0; i < size; i += PAGE_SIZE )
|
||||
{
|
||||
if( (v-u) == MAX_DIRECTMAP_MMU_QUEUE )
|
||||
if ( (v - u) == MAX_DIRECTMAP_MMU_QUEUE )
|
||||
{
|
||||
/* get the ptep's filled in */
|
||||
/* Fill in the PTE pointers. */
|
||||
__direct_remap_area_pages( mm,
|
||||
start_address,
|
||||
address-start_address,
|
||||
w);
|
||||
|
||||
count = v-u;
|
||||
if ( HYPERVISOR_mmu_update(u, &count) < 0 )
|
||||
if ( HYPERVISOR_mmu_update(u, v - u, NULL) < 0 )
|
||||
return -EFAULT;
|
||||
v=w;
|
||||
v = w;
|
||||
start_address = address;
|
||||
}
|
||||
|
||||
/* fill in the machine addresses */
|
||||
/*
|
||||
* Fill in the machine address: PTE ptr is done later by
|
||||
* __direct_remap_area_pages().
|
||||
*/
|
||||
v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot) | _PAGE_IO;
|
||||
|
||||
machine_addr += PAGE_SIZE;
|
||||
address += PAGE_SIZE;
|
||||
v++;
|
||||
}
|
||||
|
||||
if(v!=w)
|
||||
if ( v != w )
|
||||
{
|
||||
/* get the ptep's filled in */
|
||||
__direct_remap_area_pages( mm,
|
||||
start_address,
|
||||
address-start_address,
|
||||
w);
|
||||
count = v-u;
|
||||
if ( HYPERVISOR_mmu_update(u, &count) < 0 )
|
||||
__direct_remap_area_pages(mm,
|
||||
start_address,
|
||||
address-start_address,
|
||||
w);
|
||||
if ( unlikely(HYPERVISOR_mmu_update(u, v - u, NULL) < 0) )
|
||||
return -EFAULT;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -160,13 +160,15 @@ static inline int HYPERVISOR_set_trap_table(trap_info_t *table)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_mmu_update(mmu_update_t *req, int *count)
|
||||
static inline int HYPERVISOR_mmu_update(mmu_update_t *req,
|
||||
int count,
|
||||
int *success_count)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_mmu_update),
|
||||
"b" (req), "c" (count) : "memory" );
|
||||
"b" (req), "c" (count), "d" (success_count) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||