xen: pvblock: Read XenStore configuration and initialize
[platform/kernel/u-boot.git] / drivers / xen / pvblock.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) 2007-2008 Samuel Thibault.
4  * (C) Copyright 2020 EPAM Systems Inc.
5  */
6 #include <blk.h>
7 #include <common.h>
8 #include <dm.h>
9 #include <dm/device-internal.h>
10 #include <malloc.h>
11 #include <part.h>
12
13 #include <asm/armv8/mmu.h>
14 #include <asm/io.h>
15 #include <asm/xen/system.h>
16
17 #include <linux/compat.h>
18
19 #include <xen/events.h>
20 #include <xen/gnttab.h>
21 #include <xen/hvm.h>
22 #include <xen/xenbus.h>
23
24 #include <xen/interface/io/ring.h>
25 #include <xen/interface/io/blkif.h>
26 #include <xen/interface/io/protocols.h>
27
28 #define DRV_NAME        "pvblock"
29 #define DRV_NAME_BLK    "pvblock_blk"
30
31 #define O_RDONLY        00
32 #define O_RDWR          02
33
34 struct blkfront_info {
35         u64 sectors;
36         unsigned int sector_size;
37         int mode;
38         int info;
39         int barrier;
40         int flush;
41 };
42
43 /**
44  * struct blkfront_dev - Struct representing blkfront device
45  * @dom: Domain id
46  * @ring: Front_ring structure
47  * @ring_ref: The grant reference, allowing us to grant access
48  *            to the ring to the other end/domain
49  * @evtchn: Event channel used to signal ring events
50  * @handle: Events handle
51  * @nodename: Device XenStore path in format "device/vbd/" + @devid
52  * @backend: Backend XenStore path
53  * @info: Private data
54  * @devid: Device id
55  */
56 struct blkfront_dev {
57         domid_t dom;
58
59         struct blkif_front_ring ring;
60         grant_ref_t ring_ref;
61         evtchn_port_t evtchn;
62         blkif_vdev_t handle;
63
64         char *nodename;
65         char *backend;
66         struct blkfront_info info;
67         unsigned int devid;
68 };
69
70 struct blkfront_platdata {
71         unsigned int devid;
72 };
73
74 static void free_blkfront(struct blkfront_dev *dev)
75 {
76         mask_evtchn(dev->evtchn);
77         free(dev->backend);
78
79         gnttab_end_access(dev->ring_ref);
80         free(dev->ring.sring);
81
82         unbind_evtchn(dev->evtchn);
83
84         free(dev->nodename);
85         free(dev);
86 }
87
88 static void blkfront_handler(evtchn_port_t port, struct pt_regs *regs,
89                              void *data)
90 {
91         printf("%s [Port %d] - event received\n", __func__, port);
92 }
93
94 static int init_blkfront(unsigned int devid, struct blkfront_dev *dev)
95 {
96         xenbus_transaction_t xbt;
97         char *err = NULL;
98         char *message = NULL;
99         struct blkif_sring *s;
100         int retry = 0;
101         char *msg = NULL;
102         char *c;
103         char nodename[32];
104         char path[ARRAY_SIZE(nodename) + strlen("/backend-id") + 1];
105
106         sprintf(nodename, "device/vbd/%d", devid);
107
108         memset(dev, 0, sizeof(*dev));
109         dev->nodename = strdup(nodename);
110         dev->devid = devid;
111
112         snprintf(path, sizeof(path), "%s/backend-id", nodename);
113         dev->dom = xenbus_read_integer(path);
114         evtchn_alloc_unbound(dev->dom, blkfront_handler, dev, &dev->evtchn);
115
116         s = (struct blkif_sring *)memalign(PAGE_SIZE, PAGE_SIZE);
117         if (!s) {
118                 printf("Failed to allocate shared ring\n");
119                 goto error;
120         }
121
122         SHARED_RING_INIT(s);
123         FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE);
124
125         dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_pfn(s), 0);
126
127 again:
128         err = xenbus_transaction_start(&xbt);
129         if (err) {
130                 printf("starting transaction\n");
131                 free(err);
132         }
133
134         err = xenbus_printf(xbt, nodename, "ring-ref", "%u", dev->ring_ref);
135         if (err) {
136                 message = "writing ring-ref";
137                 goto abort_transaction;
138         }
139         err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
140         if (err) {
141                 message = "writing event-channel";
142                 goto abort_transaction;
143         }
144         err = xenbus_printf(xbt, nodename, "protocol", "%s",
145                             XEN_IO_PROTO_ABI_NATIVE);
146         if (err) {
147                 message = "writing protocol";
148                 goto abort_transaction;
149         }
150
151         snprintf(path, sizeof(path), "%s/state", nodename);
152         err = xenbus_switch_state(xbt, path, XenbusStateConnected);
153         if (err) {
154                 message = "switching state";
155                 goto abort_transaction;
156         }
157
158         err = xenbus_transaction_end(xbt, 0, &retry);
159         free(err);
160         if (retry) {
161                 goto again;
162                 printf("completing transaction\n");
163         }
164
165         goto done;
166
167 abort_transaction:
168         free(err);
169         err = xenbus_transaction_end(xbt, 1, &retry);
170         printf("Abort transaction %s\n", message);
171         goto error;
172
173 done:
174         snprintf(path, sizeof(path), "%s/backend", nodename);
175         msg = xenbus_read(XBT_NIL, path, &dev->backend);
176         if (msg) {
177                 printf("Error %s when reading the backend path %s\n",
178                        msg, path);
179                 goto error;
180         }
181
182         dev->handle = strtoul(strrchr(nodename, '/') + 1, NULL, 0);
183
184         {
185                 XenbusState state;
186                 char path[strlen(dev->backend) +
187                         strlen("/feature-flush-cache") + 1];
188
189                 snprintf(path, sizeof(path), "%s/mode", dev->backend);
190                 msg = xenbus_read(XBT_NIL, path, &c);
191                 if (msg) {
192                         printf("Error %s when reading the mode\n", msg);
193                         goto error;
194                 }
195                 if (*c == 'w')
196                         dev->info.mode = O_RDWR;
197                 else
198                         dev->info.mode = O_RDONLY;
199                 free(c);
200
201                 snprintf(path, sizeof(path), "%s/state", dev->backend);
202
203                 msg = NULL;
204                 state = xenbus_read_integer(path);
205                 while (!msg && state < XenbusStateConnected)
206                         msg = xenbus_wait_for_state_change(path, &state);
207                 if (msg || state != XenbusStateConnected) {
208                         printf("backend not available, state=%d\n", state);
209                         goto error;
210                 }
211
212                 snprintf(path, sizeof(path), "%s/info", dev->backend);
213                 dev->info.info = xenbus_read_integer(path);
214
215                 snprintf(path, sizeof(path), "%s/sectors", dev->backend);
216                 /*
217                  * FIXME: read_integer returns an int, so disk size
218                  * limited to 1TB for now
219                  */
220                 dev->info.sectors = xenbus_read_integer(path);
221
222                 snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
223                 dev->info.sector_size = xenbus_read_integer(path);
224
225                 snprintf(path, sizeof(path), "%s/feature-barrier",
226                          dev->backend);
227                 dev->info.barrier = xenbus_read_integer(path);
228
229                 snprintf(path, sizeof(path), "%s/feature-flush-cache",
230                          dev->backend);
231                 dev->info.flush = xenbus_read_integer(path);
232         }
233         unmask_evtchn(dev->evtchn);
234
235         debug("%llu sectors of %u bytes\n",
236               dev->info.sectors, dev->info.sector_size);
237
238         return 0;
239
240 error:
241         free(msg);
242         free(err);
243         free_blkfront(dev);
244         return -ENODEV;
245 }
246
247 static void shutdown_blkfront(struct blkfront_dev *dev)
248 {
249         char *err = NULL, *err2;
250         XenbusState state;
251
252         char path[strlen(dev->backend) + strlen("/state") + 1];
253         char nodename[strlen(dev->nodename) + strlen("/event-channel") + 1];
254
255         debug("Close " DRV_NAME ", device ID %d\n", dev->devid);
256
257         snprintf(path, sizeof(path), "%s/state", dev->backend);
258         snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
259
260         if ((err = xenbus_switch_state(XBT_NIL, nodename,
261                                        XenbusStateClosing)) != NULL) {
262                 printf("%s: error changing state to %d: %s\n", __func__,
263                        XenbusStateClosing, err);
264                 goto close;
265         }
266
267         state = xenbus_read_integer(path);
268         while (!err && state < XenbusStateClosing)
269                 err = xenbus_wait_for_state_change(path, &state);
270         free(err);
271
272         if ((err = xenbus_switch_state(XBT_NIL, nodename,
273                                        XenbusStateClosed)) != NULL) {
274                 printf("%s: error changing state to %d: %s\n", __func__,
275                        XenbusStateClosed, err);
276                 goto close;
277         }
278
279         state = xenbus_read_integer(path);
280         while (state < XenbusStateClosed) {
281                 err = xenbus_wait_for_state_change(path, &state);
282                 free(err);
283         }
284
285         if ((err = xenbus_switch_state(XBT_NIL, nodename,
286                                        XenbusStateInitialising)) != NULL) {
287                 printf("%s: error changing state to %d: %s\n", __func__,
288                        XenbusStateInitialising, err);
289                 goto close;
290         }
291
292         state = xenbus_read_integer(path);
293         while (!err &&
294                (state < XenbusStateInitWait || state >= XenbusStateClosed))
295                 err = xenbus_wait_for_state_change(path, &state);
296
297 close:
298         free(err);
299
300         snprintf(nodename, sizeof(nodename), "%s/ring-ref", dev->nodename);
301         err2 = xenbus_rm(XBT_NIL, nodename);
302         free(err2);
303         snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
304         err2 = xenbus_rm(XBT_NIL, nodename);
305         free(err2);
306
307         if (!err)
308                 free_blkfront(dev);
309 }
310
311 ulong pvblock_blk_read(struct udevice *udev, lbaint_t blknr, lbaint_t blkcnt,
312                        void *buffer)
313 {
314         return 0;
315 }
316
317 ulong pvblock_blk_write(struct udevice *udev, lbaint_t blknr, lbaint_t blkcnt,
318                         const void *buffer)
319 {
320         return 0;
321 }
322
323 static int pvblock_blk_bind(struct udevice *udev)
324 {
325         struct blk_desc *desc = dev_get_uclass_platdata(udev);
326         int devnum;
327
328         desc->if_type = IF_TYPE_PVBLOCK;
329         /*
330          * Initialize the devnum to -ENODEV. This is to make sure that
331          * blk_next_free_devnum() works as expected, since the default
332          * value 0 is a valid devnum.
333          */
334         desc->devnum = -ENODEV;
335         devnum = blk_next_free_devnum(IF_TYPE_PVBLOCK);
336         if (devnum < 0)
337                 return devnum;
338         desc->devnum = devnum;
339         desc->part_type = PART_TYPE_UNKNOWN;
340         desc->bdev = udev;
341
342         strncpy(desc->vendor, "Xen", sizeof(desc->vendor));
343         strncpy(desc->revision, "1", sizeof(desc->revision));
344         strncpy(desc->product, "Virtual disk", sizeof(desc->product));
345
346         return 0;
347 }
348
349 static int pvblock_blk_probe(struct udevice *udev)
350 {
351         struct blkfront_dev *blk_dev = dev_get_priv(udev);
352         struct blkfront_platdata *platdata = dev_get_platdata(udev);
353         struct blk_desc *desc = dev_get_uclass_platdata(udev);
354         int ret, devid;
355
356         devid = platdata->devid;
357         free(platdata);
358
359         ret = init_blkfront(devid, blk_dev);
360         if (ret < 0)
361                 return ret;
362
363         desc->blksz = blk_dev->info.sector_size;
364         desc->lba = blk_dev->info.sectors;
365         desc->log2blksz = LOG2(blk_dev->info.sector_size);
366
367         return 0;
368 }
369
370 static int pvblock_blk_remove(struct udevice *udev)
371 {
372         struct blkfront_dev *blk_dev = dev_get_priv(udev);
373
374         shutdown_blkfront(blk_dev);
375         return 0;
376 }
377
378 static const struct blk_ops pvblock_blk_ops = {
379         .read   = pvblock_blk_read,
380         .write  = pvblock_blk_write,
381 };
382
383 U_BOOT_DRIVER(pvblock_blk) = {
384         .name                   = DRV_NAME_BLK,
385         .id                     = UCLASS_BLK,
386         .ops                    = &pvblock_blk_ops,
387         .bind                   = pvblock_blk_bind,
388         .probe                  = pvblock_blk_probe,
389         .remove                 = pvblock_blk_remove,
390         .priv_auto_alloc_size   = sizeof(struct blkfront_dev),
391         .flags                  = DM_FLAG_OS_PREPARE,
392 };
393
394 /*******************************************************************************
395  * Para-virtual block device class
396  *******************************************************************************/
397
398 typedef int (*enum_vbd_callback)(struct udevice *parent, unsigned int devid);
399
400 static int on_new_vbd(struct udevice *parent, unsigned int devid)
401 {
402         struct driver_info info;
403         struct udevice *udev;
404         struct blkfront_platdata *platdata;
405         int ret;
406
407         debug("New " DRV_NAME_BLK ", device ID %d\n", devid);
408
409         platdata = malloc(sizeof(struct blkfront_platdata));
410         if (!platdata) {
411                 printf("Failed to allocate platform data\n");
412                 return -ENOMEM;
413         }
414
415         platdata->devid = devid;
416
417         info.name = DRV_NAME_BLK;
418         info.platdata = platdata;
419
420         ret = device_bind_by_name(parent, false, &info, &udev);
421         if (ret < 0) {
422                 printf("Failed to bind " DRV_NAME_BLK " to device with ID %d, ret: %d\n",
423                        devid, ret);
424                 free(platdata);
425         }
426         return ret;
427 }
428
429 static int xenbus_enumerate_vbd(struct udevice *udev, enum_vbd_callback clb)
430 {
431         char **dirs, *msg;
432         int i, ret;
433
434         msg = xenbus_ls(XBT_NIL, "device/vbd", &dirs);
435         if (msg) {
436                 printf("Failed to read device/vbd directory: %s\n", msg);
437                 free(msg);
438                 return -ENODEV;
439         }
440
441         for (i = 0; dirs[i]; i++) {
442                 int devid;
443
444                 sscanf(dirs[i], "%d", &devid);
445                 ret = clb(udev, devid);
446                 if (ret < 0)
447                         goto fail;
448
449                 free(dirs[i]);
450         }
451         ret = 0;
452
453 fail:
454         for (; dirs[i]; i++)
455                 free(dirs[i]);
456         free(dirs);
457         return ret;
458 }
459
460 void pvblock_init(void)
461 {
462         struct driver_info info;
463         struct udevice *udev;
464         struct uclass *uc;
465         int ret;
466
467         /*
468          * At this point Xen drivers have already initialized,
469          * so we can instantiate the class driver and enumerate
470          * virtual block devices.
471          */
472         info.name = DRV_NAME;
473         ret = device_bind_by_name(gd->dm_root, false, &info, &udev);
474         if (ret < 0)
475                 printf("Failed to bind " DRV_NAME ", ret: %d\n", ret);
476
477         /* Bootstrap virtual block devices class driver */
478         ret = uclass_get(UCLASS_PVBLOCK, &uc);
479         if (ret)
480                 return;
481         uclass_foreach_dev_probe(UCLASS_PVBLOCK, udev);
482 }
483
484 static int pvblock_probe(struct udevice *udev)
485 {
486         struct uclass *uc;
487         int ret;
488
489         if (xenbus_enumerate_vbd(udev, on_new_vbd) < 0)
490                 return -ENODEV;
491
492         ret = uclass_get(UCLASS_BLK, &uc);
493         if (ret)
494                 return ret;
495         uclass_foreach_dev_probe(UCLASS_BLK, udev) {
496                 if (_ret)
497                         return _ret;
498         };
499         return 0;
500 }
501
502 U_BOOT_DRIVER(pvblock_drv) = {
503         .name           = DRV_NAME,
504         .id             = UCLASS_PVBLOCK,
505         .probe          = pvblock_probe,
506 };
507
508 UCLASS_DRIVER(pvblock) = {
509         .name           = DRV_NAME,
510         .id             = UCLASS_PVBLOCK,
511 };