direct-io.hg

changeset 10611:a9c1e614c9ff

[IA64] memory exchange: use memory exchange

rewrite __xen_create_contiguous_region() and __xen_destroy_contiguous_region()
with XENMEM_exchange hypercall similar to x86.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Fri Jun 23 15:20:43 2006 -0600 (2006-06-23)
parents 39562deee9b8
children 795d31772505
files linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c	Fri Jun 23 15:16:10 2006 -0600
     1.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c	Fri Jun 23 15:20:43 2006 -0600
     1.3 @@ -161,43 +161,13 @@ static void contiguous_bitmap_clear(
     1.4  	}
     1.5  }
     1.6  
     1.7 -static unsigned long
     1.8 -HYPERVISOR_populate_physmap(unsigned long gpfn, unsigned int extent_order,
     1.9 -			    unsigned int address_bits)
    1.10 -{
    1.11 -	unsigned long ret;
    1.12 -        struct xen_memory_reservation reservation = {
    1.13 -		.nr_extents   = 1,
    1.14 -                .address_bits = address_bits,
    1.15 -                .extent_order = extent_order,
    1.16 -                .domid        = DOMID_SELF
    1.17 -        };
    1.18 -	set_xen_guest_handle(reservation.extent_start, &gpfn);
    1.19 -	ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
    1.20 -	// it may fail on non-privileged domain with extent_order > 0.
    1.21 -	BUG_ON(ret != 1 &&
    1.22 -	       !(ret == 0 && !(xen_start_info->flags & SIF_PRIVILEGED) &&
    1.23 -		 extent_order > 0));
    1.24 -	if (ret != 1)
    1.25 -		return -EINVAL;//XXX
    1.26 -	return 0;
    1.27 -}
    1.28 +// __xen_create_contiguous_region(), __xen_destroy_contiguous_region()
    1.29 +// are based on i386 xen_create_contiguous_region(),
    1.30 +// xen_destroy_contiguous_region()
    1.31  
    1.32 -static unsigned long
    1.33 -HYPERVISOR_remove_physmap(unsigned long gpfn, unsigned int extent_order)
    1.34 -{
    1.35 -	unsigned long ret;
    1.36 -	struct xen_memory_reservation reservation = {
    1.37 -		.nr_extents   = 1,
    1.38 -		.address_bits = 0,
    1.39 -		.extent_order = extent_order,
    1.40 -		.domid        = DOMID_SELF
    1.41 -	};
    1.42 -	set_xen_guest_handle(reservation.extent_start, &gpfn);
    1.43 -	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
    1.44 -	BUG_ON(ret != 1);
    1.45 -	return 0;
    1.46 -}
    1.47 +/* Protected by balloon_lock. */
    1.48 +#define MAX_CONTIG_ORDER 7
    1.49 +static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
    1.50  
    1.51  /* Ensure multi-page extents are contiguous in machine memory. */
    1.52  int
    1.53 @@ -211,57 +181,92 @@ int
    1.54  	unsigned long i;
    1.55  	unsigned long flags;
    1.56  
    1.57 +	unsigned long *in_frames = discontig_frames, out_frame;
    1.58 +	int success;
    1.59 +	struct xen_memory_exchange exchange = {
    1.60 +		.in = {
    1.61 +			.nr_extents   = num_gpfn,
    1.62 +			.extent_order = 0,
    1.63 +			.domid        = DOMID_SELF
    1.64 +		},
    1.65 +		.out = {
    1.66 +			 .nr_extents   = 1,
    1.67 +			 .extent_order = order,
    1.68 +			 .address_bits = address_bits,
    1.69 +			 .domid        = DOMID_SELF
    1.70 +		 },
    1.71 +		.nr_exchanged = 0
    1.72 +	};
    1.73 +
    1.74 +	if (order > MAX_CONTIG_ORDER)
    1.75 +		return -ENOMEM;
    1.76 +	
    1.77 +	set_xen_guest_handle(exchange.in.extent_start, in_frames);
    1.78 +	set_xen_guest_handle(exchange.out.extent_start, &out_frame);
    1.79 +
    1.80  	scrub_pages(vstart, num_gpfn);
    1.81  
    1.82  	balloon_lock(flags);
    1.83  
    1.84 -	error = HYPERVISOR_remove_physmap(start_gpfn, order);
    1.85 -	if (error) {
    1.86 -		goto fail;
    1.87 -	}
    1.88 -
    1.89 -	error = HYPERVISOR_populate_physmap(start_gpfn, order, address_bits);
    1.90 -	if (error) {
    1.91 -		goto fail;
    1.92 -	}
    1.93 -	contiguous_bitmap_set(start_gpfn, num_gpfn);
    1.94 -#if 0
    1.95 -	{
    1.96 -	unsigned long mfn;
    1.97 -	unsigned long mfn_prev = ~0UL;
    1.98 +	/* Get a new contiguous memory extent. */
    1.99  	for (i = 0; i < num_gpfn; i++) {
   1.100 -		mfn = pfn_to_mfn_for_dma(start_gpfn + i);
   1.101 -		if (mfn_prev != ~0UL && mfn != mfn_prev + 1) {
   1.102 -			xprintk("\n");
   1.103 -			xprintk("%s:%d order %d "
   1.104 -				"start 0x%lx bus 0x%lx machine 0x%lx\n",
   1.105 -				__func__, __LINE__, order,
   1.106 -				vstart, virt_to_bus((void*)vstart),
   1.107 -				phys_to_machine_for_dma(gphys));
   1.108 -			xprintk("mfn: ");
   1.109 +		in_frames[i] = start_gpfn + i;
   1.110 +	}
   1.111 +	out_frame = start_gpfn;
   1.112 +	error = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
   1.113 +	success = (exchange.nr_exchanged == num_gpfn);
   1.114 +	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (error == 0)));
   1.115 +	BUG_ON(success && (error != 0));
   1.116 +	if (unlikely(error == -ENOSYS)) {
   1.117 +		/* Compatibility when XENMEM_exchange is unsupported. */
   1.118 +		error = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
   1.119 +					     &exchange.in);
   1.120 +		BUG_ON(error != num_gpfn);
   1.121 +		error = HYPERVISOR_memory_op(XENMEM_populate_physmap,
   1.122 +					     &exchange.out);
   1.123 +		if (error != 1) {
   1.124 +			/* Couldn't get special memory: fall back to normal. */
   1.125  			for (i = 0; i < num_gpfn; i++) {
   1.126 -				mfn = pfn_to_mfn_for_dma(start_gpfn + i);
   1.127 -				xprintk("0x%lx ", mfn);
   1.128 +				in_frames[i] = start_gpfn + i;
   1.129  			}
   1.130 -			xprintk("\n");
   1.131 -			goto out;
   1.132 +			error = HYPERVISOR_memory_op(XENMEM_populate_physmap,
   1.133 +						     &exchange.in);
   1.134 +			BUG_ON(error != num_gpfn);
   1.135 +			success = 0;
   1.136 +		} else
   1.137 +			success = 1;
   1.138 +	}
   1.139 +	if (success)
   1.140 +		contiguous_bitmap_set(start_gpfn, num_gpfn);
   1.141 +#if 0
   1.142 +	if (success) {
   1.143 +		unsigned long mfn;
   1.144 +		unsigned long mfn_prev = ~0UL;
   1.145 +		for (i = 0; i < num_gpfn; i++) {
   1.146 +			mfn = pfn_to_mfn_for_dma(start_gpfn + i);
   1.147 +			if (mfn_prev != ~0UL && mfn != mfn_prev + 1) {
   1.148 +				xprintk("\n");
   1.149 +				xprintk("%s:%d order %d "
   1.150 +					"start 0x%lx bus 0x%lx "
   1.151 +					"machine 0x%lx\n",
   1.152 +					__func__, __LINE__, order,
   1.153 +					vstart, virt_to_bus((void*)vstart),
   1.154 +					phys_to_machine_for_dma(gphys));
   1.155 +				xprintk("mfn: ");
   1.156 +				for (i = 0; i < num_gpfn; i++) {
   1.157 +					mfn = pfn_to_mfn_for_dma(
   1.158 +						start_gpfn + i);
   1.159 +					xprintk("0x%lx ", mfn);
   1.160 +				}
   1.161 +				xprintk("\n");
   1.162 +				break;
   1.163 +			}
   1.164 +			mfn_prev = mfn;
   1.165  		}
   1.166 -		mfn_prev = mfn;
   1.167 -	}
   1.168  	}
   1.169  #endif
   1.170 -out:
   1.171  	balloon_unlock(flags);
   1.172 -	return error;
   1.173 -
   1.174 -fail:
   1.175 -	for (i = 0; i < num_gpfn; i++) {
   1.176 -		error = HYPERVISOR_populate_physmap(start_gpfn + i, 0, 0);
   1.177 -		if (error) {
   1.178 -			BUG();//XXX
   1.179 -		}
   1.180 -	}
   1.181 -	goto out;
   1.182 +	return success? 0: -ENOMEM;
   1.183  }
   1.184  
   1.185  void
   1.186 @@ -271,58 +276,61 @@ void
   1.187  	unsigned long error = 0;
   1.188  	unsigned long start_gpfn = __pa(vstart) >> PAGE_SHIFT;
   1.189  	unsigned long num_gpfn = 1UL << order;
   1.190 -	unsigned long* gpfns;
   1.191 -	struct xen_memory_reservation reservation;
   1.192  	unsigned long i;
   1.193  
   1.194 +	unsigned long *out_frames = discontig_frames, in_frame;
   1.195 +	int            success;
   1.196 +	struct xen_memory_exchange exchange = {
   1.197 +		.in = {
   1.198 +			.nr_extents   = 1,
   1.199 +			.extent_order = order,
   1.200 +			.domid        = DOMID_SELF
   1.201 +		},
   1.202 +		.out = {
   1.203 +			 .nr_extents   = num_gpfn,
   1.204 +			 .extent_order = 0,
   1.205 +			 .address_bits = 0,
   1.206 +			 .domid        = DOMID_SELF
   1.207 +		 },
   1.208 +		.nr_exchanged = 0
   1.209 +        };
   1.210 +	
   1.211 +
   1.212  	if (!test_bit(start_gpfn, contiguous_bitmap))
   1.213  		return;
   1.214  
   1.215 -	gpfns = kmalloc(sizeof(gpfns[0]) * num_gpfn,
   1.216 -			GFP_KERNEL | __GFP_NOFAIL);
   1.217 -	for (i = 0; i < num_gpfn; i++) {
   1.218 -		gpfns[i] = start_gpfn + i;
   1.219 -	}
   1.220 +	if (order > MAX_CONTIG_ORDER)
   1.221 +		return;
   1.222 +
   1.223 +	set_xen_guest_handle(exchange.in.extent_start, &in_frame);
   1.224 +	set_xen_guest_handle(exchange.out.extent_start, out_frames);
   1.225  
   1.226  	scrub_pages(vstart, num_gpfn);
   1.227  
   1.228  	balloon_lock(flags);
   1.229  
   1.230  	contiguous_bitmap_clear(start_gpfn, num_gpfn);
   1.231 -	error = HYPERVISOR_remove_physmap(start_gpfn, order);
   1.232 -	if (error) {
   1.233 -		goto fail;
   1.234 -	}
   1.235  
   1.236 -	set_xen_guest_handle(reservation.extent_start, gpfns);
   1.237 -	reservation.nr_extents   = num_gpfn;
   1.238 -	reservation.address_bits = 0;
   1.239 -	reservation.extent_order = 0;
   1.240 -	reservation.domid        = DOMID_SELF;
   1.241 -	error = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
   1.242 -	if (error != num_gpfn) {
   1.243 -		error = -EFAULT;//XXX
   1.244 -		goto fail;
   1.245 +        /* Do the exchange for non-contiguous MFNs. */
   1.246 +	in_frame = start_gpfn;
   1.247 +	for (i = 0; i < num_gpfn; i++) {
   1.248 +		out_frames[i] = start_gpfn + i;
   1.249  	}
   1.250 -	error = 0;
   1.251 -out:
   1.252 -	balloon_unlock(flags);
   1.253 -	kfree(gpfns);
   1.254 -	if (error) {
   1.255 -		// error can't be returned.
   1.256 -		BUG();//XXX
   1.257 -	}
   1.258 -	return;
   1.259 +	error = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
   1.260 +	success = (exchange.nr_exchanged == 1);
   1.261 +	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (error == 0)));
   1.262 +	BUG_ON(success && (error != 0));
   1.263 +	if (unlikely(error == -ENOSYS)) {
   1.264 +                /* Compatibility when XENMEM_exchange is unsupported. */
   1.265 +		error = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
   1.266 +					     &exchange.in);
   1.267 +		BUG_ON(error != 1);
   1.268  
   1.269 -fail:
   1.270 -	for (i = 0; i < num_gpfn; i++) {
   1.271 -		int tmp_error;// don't overwrite error.
   1.272 -		tmp_error = HYPERVISOR_populate_physmap(start_gpfn + i, 0, 0);
   1.273 -		if (tmp_error) {
   1.274 -			BUG();//XXX
   1.275 -		}
   1.276 +		error = HYPERVISOR_memory_op(XENMEM_populate_physmap,
   1.277 +					     &exchange.out);
   1.278 +		BUG_ON(error != num_gpfn);
   1.279  	}
   1.280 -	goto out;
   1.281 +	balloon_unlock(flags);
   1.282  }
   1.283  
   1.284