1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2010 - 2015 UNISYS CORPORATION
4  * All rights reserved.
5  */
6 
7 /*
8  *  This provides s-Par channel communication primitives, which are
9  *  independent of the mechanism used to access the channel data.
10  */
11 
12 #include <linux/uuid.h>
13 #include <linux/io.h>
14 #include <linux/slab.h>
15 #include <linux/visorbus.h>
16 
17 #include "visorbus_private.h"
18 #include "controlvmchannel.h"
19 
20 #define VISOR_DRV_NAME "visorchannel"
21 
22 #define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
23 	GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
24 		  0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
25 
26 static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
27 
28 struct visorchannel {
29 	u64 physaddr;
30 	ulong nbytes;
31 	void *mapped;
32 	bool requested;
33 	struct channel_header chan_hdr;
34 	guid_t guid;
35 	/*
36 	 * channel creator knows if more than one thread will be inserting or
37 	 * removing
38 	 */
39 	bool needs_lock;
40 	/* protect head writes in chan_hdr */
41 	spinlock_t insert_lock;
42 	/* protect tail writes in chan_hdr */
43 	spinlock_t remove_lock;
44 	guid_t type;
45 	guid_t inst;
46 };
47 
visorchannel_destroy(struct visorchannel * channel)48 void visorchannel_destroy(struct visorchannel *channel)
49 {
50 	if (!channel)
51 		return;
52 
53 	if (channel->mapped) {
54 		memunmap(channel->mapped);
55 		if (channel->requested)
56 			release_mem_region(channel->physaddr, channel->nbytes);
57 	}
58 	kfree(channel);
59 }
60 
visorchannel_get_physaddr(struct visorchannel * channel)61 u64 visorchannel_get_physaddr(struct visorchannel *channel)
62 {
63 	return channel->physaddr;
64 }
65 
visorchannel_get_nbytes(struct visorchannel * channel)66 ulong visorchannel_get_nbytes(struct visorchannel *channel)
67 {
68 	return channel->nbytes;
69 }
70 
visorchannel_guid_id(const guid_t * guid,char * s)71 char *visorchannel_guid_id(const guid_t *guid, char *s)
72 {
73 	sprintf(s, "%pUL", guid);
74 	return s;
75 }
76 
visorchannel_id(struct visorchannel * channel,char * s)77 char *visorchannel_id(struct visorchannel *channel, char *s)
78 {
79 	return visorchannel_guid_id(&channel->guid, s);
80 }
81 
visorchannel_zoneid(struct visorchannel * channel,char * s)82 char *visorchannel_zoneid(struct visorchannel *channel, char *s)
83 {
84 	return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
85 }
86 
visorchannel_get_clientpartition(struct visorchannel * channel)87 u64 visorchannel_get_clientpartition(struct visorchannel *channel)
88 {
89 	return channel->chan_hdr.partition_handle;
90 }
91 
visorchannel_set_clientpartition(struct visorchannel * channel,u64 partition_handle)92 int visorchannel_set_clientpartition(struct visorchannel *channel,
93 				     u64 partition_handle)
94 {
95 	channel->chan_hdr.partition_handle = partition_handle;
96 	return 0;
97 }
98 
99 /**
100  * visorchannel_get_guid() - queries the GUID of the designated channel
101  * @channel: the channel to query
102  *
103  * Return: the GUID of the provided channel
104  */
visorchannel_get_guid(struct visorchannel * channel)105 const guid_t *visorchannel_get_guid(struct visorchannel *channel)
106 {
107 	return &channel->guid;
108 }
109 EXPORT_SYMBOL_GPL(visorchannel_get_guid);
110 
visorchannel_read(struct visorchannel * channel,ulong offset,void * dest,ulong nbytes)111 int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
112 		      ulong nbytes)
113 {
114 	if (offset + nbytes > channel->nbytes)
115 		return -EIO;
116 
117 	memcpy(dest, channel->mapped + offset, nbytes);
118 	return 0;
119 }
120 
visorchannel_write(struct visorchannel * channel,ulong offset,void * dest,ulong nbytes)121 int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
122 		       ulong nbytes)
123 {
124 	size_t chdr_size = sizeof(struct channel_header);
125 	size_t copy_size;
126 
127 	if (offset + nbytes > channel->nbytes)
128 		return -EIO;
129 
130 	if (offset < chdr_size) {
131 		copy_size = min(chdr_size - offset, nbytes);
132 		memcpy(((char *)(&channel->chan_hdr)) + offset,
133 		       dest, copy_size);
134 	}
135 	memcpy(channel->mapped + offset, dest, nbytes);
136 	return 0;
137 }
138 
visorchannel_get_header(struct visorchannel * channel)139 void *visorchannel_get_header(struct visorchannel *channel)
140 {
141 	return &channel->chan_hdr;
142 }
143 
144 /*
145  * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
146  * channel header
147  */
sig_queue_offset(struct channel_header * chan_hdr,int q)148 static int sig_queue_offset(struct channel_header *chan_hdr, int q)
149 {
150 	return ((chan_hdr)->ch_space_offset +
151 	       ((q) * sizeof(struct signal_queue_header)));
152 }
153 
154 /*
155  * Return offset of a specific queue entry (data) from the beginning of a
156  * channel header
157  */
sig_data_offset(struct channel_header * chan_hdr,int q,struct signal_queue_header * sig_hdr,int slot)158 static int sig_data_offset(struct channel_header *chan_hdr, int q,
159 			   struct signal_queue_header *sig_hdr, int slot)
160 {
161 	return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
162 	       (slot * sig_hdr->signal_size));
163 }
164 
165 /*
166  * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into
167  * host memory
168  */
169 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
170 	visorchannel_write(channel, \
171 			   sig_queue_offset(&channel->chan_hdr, queue) + \
172 			   offsetof(struct signal_queue_header, FIELD), \
173 			   &((sig_hdr)->FIELD), \
174 			   sizeof((sig_hdr)->FIELD))
175 
sig_read_header(struct visorchannel * channel,u32 queue,struct signal_queue_header * sig_hdr)176 static int sig_read_header(struct visorchannel *channel, u32 queue,
177 			   struct signal_queue_header *sig_hdr)
178 {
179 	if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
180 		return -EINVAL;
181 
182 	/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
183 	return visorchannel_read(channel,
184 				 sig_queue_offset(&channel->chan_hdr, queue),
185 				 sig_hdr, sizeof(struct signal_queue_header));
186 }
187 
sig_read_data(struct visorchannel * channel,u32 queue,struct signal_queue_header * sig_hdr,u32 slot,void * data)188 static int sig_read_data(struct visorchannel *channel, u32 queue,
189 			 struct signal_queue_header *sig_hdr, u32 slot,
190 			 void *data)
191 {
192 	int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
193 						 sig_hdr, slot);
194 
195 	return visorchannel_read(channel, signal_data_offset,
196 				 data, sig_hdr->signal_size);
197 }
198 
sig_write_data(struct visorchannel * channel,u32 queue,struct signal_queue_header * sig_hdr,u32 slot,void * data)199 static int sig_write_data(struct visorchannel *channel, u32 queue,
200 			  struct signal_queue_header *sig_hdr, u32 slot,
201 			  void *data)
202 {
203 	int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
204 						 sig_hdr, slot);
205 
206 	return visorchannel_write(channel, signal_data_offset,
207 				  data, sig_hdr->signal_size);
208 }
209 
signalremove_inner(struct visorchannel * channel,u32 queue,void * msg)210 static int signalremove_inner(struct visorchannel *channel, u32 queue,
211 			      void *msg)
212 {
213 	struct signal_queue_header sig_hdr;
214 	int error;
215 
216 	error = sig_read_header(channel, queue, &sig_hdr);
217 	if (error)
218 		return error;
219 	/* No signals to remove; have caller try again. */
220 	if (sig_hdr.head == sig_hdr.tail)
221 		return -EAGAIN;
222 	sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
223 	error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
224 	if (error)
225 		return error;
226 	sig_hdr.num_received++;
227 	/*
228 	 * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
229 	 * host memory. Required for channel sync.
230 	 */
231 	mb();
232 	error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
233 	if (error)
234 		return error;
235 	error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
236 	if (error)
237 		return error;
238 	return 0;
239 }
240 
241 /**
242  * visorchannel_signalremove() - removes a message from the designated
243  *                               channel/queue
244  * @channel: the channel the message will be removed from
245  * @queue:   the queue the message will be removed from
246  * @msg:     the message to remove
247  *
248  * Return: integer error code indicating the status of the removal
249  */
visorchannel_signalremove(struct visorchannel * channel,u32 queue,void * msg)250 int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
251 			      void *msg)
252 {
253 	int rc;
254 	unsigned long flags;
255 
256 	if (channel->needs_lock) {
257 		spin_lock_irqsave(&channel->remove_lock, flags);
258 		rc = signalremove_inner(channel, queue, msg);
259 		spin_unlock_irqrestore(&channel->remove_lock, flags);
260 	} else {
261 		rc = signalremove_inner(channel, queue, msg);
262 	}
263 
264 	return rc;
265 }
266 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
267 
queue_empty(struct visorchannel * channel,u32 queue)268 static bool queue_empty(struct visorchannel *channel, u32 queue)
269 {
270 	struct signal_queue_header sig_hdr;
271 
272 	if (sig_read_header(channel, queue, &sig_hdr))
273 		return true;
274 	return (sig_hdr.head == sig_hdr.tail);
275 }
276 
277 /**
278  * visorchannel_signalempty() - checks if the designated channel/queue contains
279  *				any messages
280  * @channel: the channel to query
281  * @queue:   the queue in the channel to query
282  *
283  * Return: boolean indicating whether any messages in the designated
284  *         channel/queue are present
285  */
visorchannel_signalempty(struct visorchannel * channel,u32 queue)286 bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
287 {
288 	bool rc;
289 	unsigned long flags;
290 
291 	if (!channel->needs_lock)
292 		return queue_empty(channel, queue);
293 	spin_lock_irqsave(&channel->remove_lock, flags);
294 	rc = queue_empty(channel, queue);
295 	spin_unlock_irqrestore(&channel->remove_lock, flags);
296 	return rc;
297 }
298 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
299 
signalinsert_inner(struct visorchannel * channel,u32 queue,void * msg)300 static int signalinsert_inner(struct visorchannel *channel, u32 queue,
301 			      void *msg)
302 {
303 	struct signal_queue_header sig_hdr;
304 	int err;
305 
306 	err = sig_read_header(channel, queue, &sig_hdr);
307 	if (err)
308 		return err;
309 	sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
310 	if (sig_hdr.head == sig_hdr.tail) {
311 		sig_hdr.num_overflows++;
312 		err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows);
313 		if (err)
314 			return err;
315 		return -EIO;
316 	}
317 	err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
318 	if (err)
319 		return err;
320 	sig_hdr.num_sent++;
321 	/*
322 	 * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
323 	 * host memory. Required for channel sync.
324 	 */
325 	mb();
326 	err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
327 	if (err)
328 		return err;
329 	err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
330 	if (err)
331 		return err;
332 	return 0;
333 }
334 
335 /*
336  * visorchannel_create() - creates the struct visorchannel abstraction for a
337  *                         data area in memory, but does NOT modify this data
338  *                         area
339  * @physaddr:      physical address of start of channel
340  * @gfp:           gfp_t to use when allocating memory for the data struct
341  * @guid:          GUID that identifies channel type;
342  * @needs_lock:    must specify true if you have multiple threads of execution
343  *                 that will be calling visorchannel methods of this
344  *                 visorchannel at the same time
345  *
346  * Return: pointer to visorchannel that was created if successful,
347  *         otherwise NULL
348  */
visorchannel_create(u64 physaddr,gfp_t gfp,const guid_t * guid,bool needs_lock)349 struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
350 					 const guid_t *guid, bool needs_lock)
351 {
352 	struct visorchannel *channel;
353 	int err;
354 	size_t size = sizeof(struct channel_header);
355 
356 	if (physaddr == 0)
357 		return NULL;
358 
359 	channel = kzalloc(sizeof(*channel), gfp);
360 	if (!channel)
361 		return NULL;
362 	channel->needs_lock = needs_lock;
363 	spin_lock_init(&channel->insert_lock);
364 	spin_lock_init(&channel->remove_lock);
365 	/*
366 	 * Video driver constains the efi framebuffer so it will get a conflict
367 	 * resource when requesting its full mem region. Since we are only
368 	 * using the efi framebuffer for video we can ignore this. Remember that
369 	 * we haven't requested it so we don't try to release later on.
370 	 */
371 	channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
372 	if (!channel->requested && !guid_equal(guid, &visor_video_guid))
373 		/* we only care about errors if this is not the video channel */
374 		goto err_destroy_channel;
375 	channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
376 	if (!channel->mapped) {
377 		release_mem_region(physaddr, size);
378 		goto err_destroy_channel;
379 	}
380 	channel->physaddr = physaddr;
381 	channel->nbytes = size;
382 	err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
383 	if (err)
384 		goto err_destroy_channel;
385 	size = (ulong)channel->chan_hdr.size;
386 	memunmap(channel->mapped);
387 	if (channel->requested)
388 		release_mem_region(channel->physaddr, channel->nbytes);
389 	channel->mapped = NULL;
390 	channel->requested = request_mem_region(channel->physaddr, size,
391 						VISOR_DRV_NAME);
392 	if (!channel->requested && !guid_equal(guid, &visor_video_guid))
393 		/* we only care about errors if this is not the video channel */
394 		goto err_destroy_channel;
395 	channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
396 	if (!channel->mapped) {
397 		release_mem_region(channel->physaddr, size);
398 		goto err_destroy_channel;
399 	}
400 	channel->nbytes = size;
401 	guid_copy(&channel->guid, guid);
402 	return channel;
403 
404 err_destroy_channel:
405 	visorchannel_destroy(channel);
406 	return NULL;
407 }
408 
409 /**
410  * visorchannel_signalinsert() - inserts a message into the designated
411  *                               channel/queue
412  * @channel: the channel the message will be added to
413  * @queue:   the queue the message will be added to
414  * @msg:     the message to insert
415  *
416  * Return: integer error code indicating the status of the insertion
417  */
visorchannel_signalinsert(struct visorchannel * channel,u32 queue,void * msg)418 int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
419 			      void *msg)
420 {
421 	int rc;
422 	unsigned long flags;
423 
424 	if (channel->needs_lock) {
425 		spin_lock_irqsave(&channel->insert_lock, flags);
426 		rc = signalinsert_inner(channel, queue, msg);
427 		spin_unlock_irqrestore(&channel->insert_lock, flags);
428 	} else {
429 		rc = signalinsert_inner(channel, queue, msg);
430 	}
431 
432 	return rc;
433 }
434 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
435