version 1.6, 2006/01/15 22:09:52 |
version 1.7, 2006/08/28 19:58:57 |
Line 75 _xen_alloc_contig(bus_size_t size, bus_s |
|
Line 75 _xen_alloc_contig(bus_size_t size, bus_s |
|
unsigned long npagesreq, npages, mfn; |
unsigned long npagesreq, npages, mfn; |
bus_addr_t pa; |
bus_addr_t pa; |
struct vm_page *pg, *pgnext; |
struct vm_page *pg, *pgnext; |
struct pglist freelist; |
|
int s, error; |
int s, error; |
#ifdef XEN3 |
#ifdef XEN3 |
struct xen_memory_reservation res; |
struct xen_memory_reservation res; |
#endif |
#endif |
|
|
TAILQ_INIT(&freelist); |
|
|
|
/* |
/* |
* When requesting a contigous memory region, the hypervisor will |
* When requesting a contigous memory region, the hypervisor will |
* return a memory range aligned on size. This will automagically |
* return a memory range aligned on size. This will automagically |
Line 114 _xen_alloc_contig(bus_size_t size, bus_s |
|
Line 111 _xen_alloc_contig(bus_size_t size, bus_s |
|
< 0) { |
< 0) { |
printf("xen_alloc_contig: XENMEM_decrease_reservation " |
printf("xen_alloc_contig: XENMEM_decrease_reservation " |
"failed!\n"); |
"failed!\n"); |
return ENOMEM; |
xpmap_phys_to_machine_mapping[ |
|
(pa - XPMAP_OFFSET) >> PAGE_SHIFT] = mfn; |
|
|
|
error = ENOMEM; |
|
goto failed; |
} |
} |
#else |
#else |
if (HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, |
if (HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, |
&mfn, 1, 0) != 1) { |
&mfn, 1, 0) != 1) { |
printf("xen_alloc_contig: MEMOP_decrease_reservation " |
printf("xen_alloc_contig: MEMOP_decrease_reservation " |
"failed!\n"); |
"failed!\n"); |
return ENOMEM; |
xpmap_phys_to_machine_mapping[ |
|
(pa - XPMAP_OFFSET) >> PAGE_SHIFT] = mfn; |
|
error = ENOMEM; |
|
goto failed; |
} |
} |
#endif |
#endif |
} |
} |
Line 135 _xen_alloc_contig(bus_size_t size, bus_s |
|
Line 139 _xen_alloc_contig(bus_size_t size, bus_s |
|
if (HYPERVISOR_memory_op(XENMEM_increase_reservation, &res) < 0) { |
if (HYPERVISOR_memory_op(XENMEM_increase_reservation, &res) < 0) { |
printf("xen_alloc_contig: XENMEM_increase_reservation " |
printf("xen_alloc_contig: XENMEM_increase_reservation " |
"failed!\n"); |
"failed!\n"); |
return ENOMEM; |
error = ENOMEM; |
|
pg = NULL; |
|
goto failed; |
} |
} |
#else |
#else |
if (HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, |
if (HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, |
&mfn, 1, order) != 1) { |
&mfn, 1, order) != 1) { |
printf("xen_alloc_contig: MEMOP_increase_reservation " |
printf("xen_alloc_contig: MEMOP_increase_reservation " |
"failed!\n"); |
"failed!\n"); |
return ENOMEM; |
error = ENOMEM; |
|
pg = NULL; |
|
goto failed; |
} |
} |
#endif |
#endif |
s = splvm(); |
s = splvm(); |
Line 165 _xen_alloc_contig(bus_size_t size, bus_s |
|
Line 173 _xen_alloc_contig(bus_size_t size, bus_s |
|
xpq_flush_queue(); |
xpq_flush_queue(); |
splx(s); |
splx(s); |
return 0; |
return 0; |
|
|
|
failed: |
|
/* |
|
* Attempt to recover from a failed decrease or increase reservation: |
|
* if decrease_reservation failed, we don't have given all pages |
|
* back to Xen; give them back to UVM, and get the missing pages |
|
* from Xen. |
|
* if increase_reservation failed, we expect pg to be NULL and we just |
|
* get back the missing pages from Xen one by one. |
|
*/ |
|
/* give back remaining pages to UVM */ |
|
for (; pg != NULL; pg = pgnext) { |
|
pgnext = pg->pageq.tqe_next; |
|
TAILQ_REMOVE(mlistp, pg, pageq); |
|
uvm_pagefree(pg); |
|
} |
|
/* remplace the pages that we already gave to Xen */ |
|
s = splvm(); |
|
for (pg = mlistp->tqh_first; pg != NULL; pg = pgnext) { |
|
pgnext = pg->pageq.tqe_next; |
|
#ifdef XEN3 |
|
res.extent_start = &mfn; |
|
res.nr_extents = 1; |
|
res.extent_order = 0; |
|
res.address_bits = 31; |
|
res.domid = DOMID_SELF; |
|
if (HYPERVISOR_memory_op(XENMEM_increase_reservation, &res) |
|
< 0) { |
|
printf("xen_alloc_contig: recovery " |
|
"XENMEM_increase_reservation failed!\n"); |
|
break; |
|
} |
|
#else |
|
if (HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, |
|
&mfn, 1, 0) != 1) { |
|
printf("xen_alloc_contig: recovery " |
|
"MEMOP_increase_reservation failed!\n"); |
|
break; |
|
} |
|
#endif |
|
pa = VM_PAGE_TO_PHYS(pg); |
|
xpmap_phys_to_machine_mapping[ |
|
(pa - XPMAP_OFFSET) >> PAGE_SHIFT] = mfn; |
|
xpq_queue_machphys_update((mfn) << PAGE_SHIFT, pa); |
|
TAILQ_REMOVE(mlistp, pg, pageq); |
|
uvm_pagefree(pg); |
|
} |
|
/* Flush updates through and flush the TLB */ |
|
xpq_queue_tlb_flush(); |
|
xpq_flush_queue(); |
|
splx(s); |
|
return error; |
} |
} |
|
|
|
|
Line 178 _xen_bus_dmamem_alloc_range(bus_dma_tag_ |
|
Line 238 _xen_bus_dmamem_alloc_range(bus_dma_tag_ |
|
bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, |
bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, |
int nsegs, int *rsegs, int flags, bus_addr_t low, bus_addr_t high) |
int nsegs, int *rsegs, int flags, bus_addr_t low, bus_addr_t high) |
{ |
{ |
paddr_t curaddr, lastaddr; |
bus_addr_t curaddr, lastaddr; |
bus_addr_t bus_curaddr, bus_lastaddr; |
|
struct vm_page *m; |
struct vm_page *m; |
struct pglist mlist; |
struct pglist mlist; |
int curseg, error; |
int curseg, error; |
|
|
*/ |
*/ |
m = mlist.tqh_first; |
m = mlist.tqh_first; |
curseg = 0; |
curseg = 0; |
lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m); |
lastaddr = segs[curseg].ds_addr = _BUS_VM_PAGE_TO_BUS(m); |
segs[curseg].ds_len = PAGE_SIZE; |
segs[curseg].ds_len = PAGE_SIZE; |
m = m->pageq.tqe_next; |
m = m->pageq.tqe_next; |
if ((_BUS_PHYS_TO_BUS(segs[curseg].ds_addr) & (alignment - 1)) != 0) |
if ((segs[curseg].ds_addr & (alignment - 1)) != 0) |
goto dorealloc; |
goto dorealloc; |
|
|
for (; m != NULL; m = m->pageq.tqe_next) { |
for (; m != NULL; m = m->pageq.tqe_next) { |
curaddr = VM_PAGE_TO_PHYS(m); |
curaddr = _BUS_VM_PAGE_TO_BUS(m); |
bus_curaddr = _BUS_PHYS_TO_BUS(curaddr); |
if ((lastaddr < low || lastaddr >= high) || |
bus_lastaddr = _BUS_PHYS_TO_BUS(lastaddr); |
(curaddr < low || curaddr >= high)) { |
if ((bus_lastaddr < low || bus_lastaddr >= high) || |
|
(bus_curaddr < low || bus_curaddr >= high)) { |
|
/* |
/* |
* If machine addresses are outside the allowed |
* If machine addresses are outside the allowed |
* range we have to bail. Xen2 doesn't offer an |
* range we have to bail. Xen2 doesn't offer an |
|
|
uvm_pglistfree(&mlist); |
uvm_pglistfree(&mlist); |
return EINVAL; |
return EINVAL; |
} |
} |
if (bus_curaddr == (bus_lastaddr + PAGE_SIZE)) { |
if (curaddr == (lastaddr + PAGE_SIZE)) { |
segs[curseg].ds_len += PAGE_SIZE; |
segs[curseg].ds_len += PAGE_SIZE; |
if ((bus_lastaddr & boundary) != |
if ((lastaddr & boundary) != |
(bus_curaddr & boundary)) |
(curaddr & boundary)) |
goto dorealloc; |
goto dorealloc; |
} |
} else { |
else { |
|
curseg++; |
curseg++; |
if (curseg >= nsegs || |
if (curseg >= nsegs || |
(bus_curaddr & (alignment - 1)) != 0) { |
(curaddr & (alignment - 1)) != 0) { |
dorealloc: |
dorealloc: |
if (doingrealloc == 1) |
if (doingrealloc == 1) |
panic("_xen_bus_dmamem_alloc_range: " |
panic("_xen_bus_dmamem_alloc_range: " |