@@ -7,9 +7,9 @@ to run graphical snaps like `ubuntu-frame` or any other *Mir*-based
7
7
compositor in a snapped environment.
8
8
9
9
To this end, we will accomplish the following in order:
10
- - Assemble a ` graphics-core22 ` snap
11
- - Test the assembled snap
12
- - Confirm that ` ubuntu-frame ` runs in your environment
10
+ - How to assemble a ` graphics-core22 ` provider snap
11
+ - How to test a ` graphics-core22 ` provider snap
12
+ - How to test the confinement of your * Mir * -based snap that relies on the provider snap
13
13
14
14
## Prerequisites
15
15
Before we get started, let's make sure that we have everything that we require.
@@ -96,7 +96,7 @@ While *Mir* can be enabled on platforms that do not support `GBM/KMS`, this
96
96
requires a paltform implementation to be written in * Mir* . This work is out
97
97
of the scope of this guide.
98
98
99
- ## Assemble a ` graphics-core22 ` snap
99
+ ## How to assemble a ` graphics-core22 ` provider snap
100
100
With the prerequisites out of the way, it is time to assemble a
101
101
` graphics-core22 ` snap.
102
102
@@ -190,7 +190,9 @@ parts:
190
190
- graphics/lib/*
191
191
` ` `
192
192
193
- # ## Possible complications
193
+ When you're ready, build your snap using `snapcraft`.
194
+
195
+ # ## Troubleshooting
194
196
There are a number of ways the vendor drivers can differ from this simplest case, requiring different solutions.
195
197
Let's explore a few of them.
196
198
@@ -258,4 +260,196 @@ The [mesa-core22](https://github.com/canonical/mesa-core22/blob/main/snap/snapcr
258
260
directory is shipped in a top-level `glvnd` path, under the path exported by the
259
261
` graphics-core22` slot.
260
262
261
- .
263
+ # # How to test a `graphics-core22` provider snap
264
+ Now we have our `graphics-core22` provider snap built. However, we don't yet know if it works
265
+ properly. Testing this snap is our next task.
266
+
267
+ For starters, install the [graphics-test-tools](https://snapcraft.io/graphics-test-tools) snap :
268
+
269
+ ` ` ` shell
270
+ sudo snap install graphics-test-tools --channel 22/stable
271
+ ` ` `
272
+
273
+ Next, connect the snap that you've built to `graphics-test-tools` :
274
+
275
+ ` ` ` shell
276
+ sudo snap connect graphics-test-tools:graphics-core22 <your-snap>:graphics-core22
277
+ ` ` `
278
+
279
+ With that installed, we can begin testing.
280
+
281
+ # ## Use `eglinfo` to test
282
+ This is the most basic test that can be performed, and is a good indication of baseline GPU
283
+ driver setup. This should list _at least_ a GBM platform with the expected vendor and
284
+ `OpenGL_ES` client API. An abbreviated example (on a `mesa-core22` system) :
285
+
286
+ ` ` `
287
+ $ graphics-test-tools.eglinfo
288
+ EGL client extensions string:
289
+ EGL_EXT_device_base EGL_EXT_device_enumeration EGL_EXT_device_query
290
+ EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses
291
+ EGL_EXT_client_extensions EGL_KHR_debug EGL_EXT_platform_device
292
+ EGL_EXT_platform_wayland EGL_KHR_platform_wayland
293
+ EGL_EXT_platform_x11 EGL_KHR_platform_x11 EGL_EXT_platform_xcb
294
+ EGL_MESA_platform_gbm EGL_KHR_platform_gbm
295
+ EGL_MESA_platform_surfaceless
296
+
297
+
298
+ GBM platform:
299
+ EGL API version: 1.5
300
+ EGL vendor string: Mesa Project
301
+ EGL version string: 1.5
302
+ EGL client APIs: OpenGL OpenGL_ES
303
+ EGL driver name: iris
304
+ EGL extensions string:
305
+ EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync
306
+ EGL_EXT_buffer_age EGL_EXT_create_context_robustness
307
+ EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers
308
+ EGL_IMG_context_priority EGL_KHR_cl_event2 EGL_KHR_config_attribs
309
+ EGL_KHR_context_flush_control EGL_KHR_create_context
310
+ EGL_KHR_create_context_no_error EGL_KHR_fence_sync
311
+ EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace
312
+ EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image
313
+ EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image
314
+ EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap
315
+ EGL_KHR_no_config_context EGL_KHR_reusable_sync
316
+ EGL_KHR_surfaceless_context EGL_EXT_pixel_format_float
317
+ EGL_KHR_wait_sync EGL_MESA_configless_context EGL_MESA_drm_image
318
+ EGL_MESA_image_dma_buf_export EGL_MESA_query_driver
319
+ EGL_WL_bind_wayland_display
320
+ Configurations:
321
+ bf lv colorbuffer dp st ms vis cav bi renderable supported
322
+ id sz l r g b a th cl ns b id eat nd gl es es2 vg surfaces
323
+ ---------------------------------------------------------------------
324
+ 0x01 32 0 10 10 10 2 0 0 0 0 0x30335241-- y y y win
325
+ 0x02 32 0 10 10 10 2 16 0 0 0 0x30335241-- y y y win
326
+ 0x03 32 0 10 10 10 2 24 0 0 0 0x30335241-- y y y win
327
+ 0x04 32 0 10 10 10 2 24 8 0 0 0x30335241-- y y y win
328
+ 0x05 32 0 10 10 10 2 0 0 2 1 0x30335241-- y y y win
329
+ … lots more configurations, then other platform details …
330
+ ` ` `
331
+
332
+ If `eglinfo` does **NOT** list a GBM platform, or generates errors then you want to look
333
+ at [possible complications](#possible-complications). If `eglinfo` does list a GBM platform
334
+ then we can proceed to testing `ubuntu-frame`.
335
+
336
+ # ## Test if `ubuntu-frame` works
337
+ First, install `ubuntu-frame` :
338
+ ` ` ` shell
339
+ sudo snap install ubuntu-frame --devmode
340
+ ` ` `
341
+
342
+ Next, disconnect it from the default graphics interface :
343
+ ` ` ` shell
344
+ sudo snap disconnect ubuntu-frame:graphics-core22
345
+ ` ` `
346
+
347
+ Then, connect it to your new provider snap :
348
+ ` ` ` shell
349
+ sudo snap connect ubuntu-frame:graphics-core22 <your-snap>:graphics-core22
350
+ ` ` `
351
+
352
+ Finally, run `ubuntu-frame` :
353
+ ` ` ` shell
354
+ ubuntu-frame
355
+ ` ` `
356
+
357
+ If everything previously has gone correctly this should result in `ubuntu-frame` coming
358
+ up on the connected outputs. If not, the log messages will hopefully help identify issues.
359
+
360
+ # # How to test the confinement of your *Mir*-based snap
361
+ Once you have your `graphics-core22` provider snap setup, and you are confident that it works
362
+ well, you'll want to make sure that you can run the snap that *depends on* your provider snap
363
+ in a confined mode. Since we already have `ubuntu-frame` setup, we will use it as an example.
364
+ However, you should be able to run these tests on any *Mir*-based snap.
365
+
366
+ First, let's uninstall `ubuntu-frame` if it is installed :
367
+
368
+ ` ` ` shell
369
+ sudo snap remove ubuntu-frame
370
+ ` ` `
371
+
372
+ Next, we can install `ubuntu-frame` without the `--devmode` flag :
373
+ ` ` ` shell
374
+ sudo snap install ubuntu-frame
375
+ sudo snap disconnect ubuntu-frame:graphics-core22
376
+ ` ` `
377
+
378
+ Finally, we will run `ubuntu-frame` like before :
379
+ ` ` ` shell
380
+ ubuntu-frame
381
+ ` ` `
382
+
383
+ If everything works, then `ubuntu-frame` is ready. If not, we'll have to troubleshoot.
384
+
385
+ # ## Troubleshooting
386
+ When bringing up a confined ubuntu-frame snap on a new board with new drivers there are two
387
+ separate access control mechanisms :
388
+ - AppArmor
389
+ - The devices cgroup
390
+
391
+ # ### AppArmor
392
+ The first is relatively easy to debug. When AppArmor would deny access to a resource, it outputs a nice
393
+ message in `dmesg` :
394
+
395
+ ` ` `
396
+ apparmor="DENIED" operation="open" profile="snap.ubuntu-frame.ubuntu-frame" name="/run/udev/data/c189:1" <other stuff>
397
+ ` ` `
398
+
399
+ You can find the AppArmor profile at `/var/lib/snapd/apparmor/profiles/snap.ubuntu-frame.ubuntu-frame`.
400
+ Make modifications to the profile using your favorite text editor. Finally, apply the change to replace
401
+ the default confinement :
402
+
403
+ ` ` ` shell
404
+ sudo apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.ubuntu-frame.ubuntu-frame
405
+ ` ` `
406
+
407
+ # ### The devices cgroup
408
+ The cgroup confinement is less easy to debug. The kernel emits no logs when the devices cgroup
409
+ denies access to a device node. The device node on the filesystem will appear to have the correct
410
+ permissions (and, for example, you will be able to touch it), but calls to `open()` will fail
411
+ with `EPERM`. If everything seems to be set up correctly, and there are no errors in `dmesg`,
412
+ but `Mir` is failing it’s likely that the devices cgroup confinement is to blame.
413
+
414
+ Additionally, it is more difficult to test as the cgroup is only set up during snap run startup,
415
+ and so the knobs we need to twiddle only exist while the snap is running.
416
+
417
+ We can get around this by running :
418
+ ` ` ` shell
419
+ snap run --shell ubuntu-frame
420
+ ` ` `
421
+ This command will get snapd to do all the initialisation and drop us into a shell.
422
+ Once the shell exists, there will be two(?!) cgroup folders found under `/sys/fs/cgroup/devices` :
423
+ 1. /sys/fs/cgroup/devices/system.slice/snap.ubuntu-frame.ubuntu-frame.${UUID}.scope, and
424
+ 2. /sys/fs/cgroup/devices/snap.ubuntu-frame.ubuntu-frame
425
+
426
+ It is (2) that we’re after. You can check that you’ve got the right directory, because the
427
+ `devices.list` file will contain a bunch of lines like :
428
+
429
+ ` ` `
430
+ c 5:1 rwm
431
+ c 5:2 rwm
432
+ c 136:* rwm
433
+ c 137:* rwm
434
+ c 138:* rwm
435
+ ` ` `
436
+
437
+ You now need to give the cgroup permission to access the necessary devices, for which you need
438
+ the `major:minor` of the device nodes. You can find that with ls :
439
+ ` ` `
440
+ $ ls -la /sys/fs/cgroup/devices/snap.ubuntu-frame.ubuntu-frame
441
+ crw-rw-rw- 1 root root 10, 60 Jan 10 04:56 /dev/mali0
442
+ ` ` `
443
+
444
+ Here we see that the `/dev/mali0` device node has `major:minor` equal to `10:60`.
445
+
446
+ Now we can enable access to the relevant device node, via :
447
+ ` ` ` shell
448
+ echo "c 10:60 rw" | sudo tee /sys/fs/cgroup/devices/snap.ubuntu-frame.ubuntu-frame/devices.allow
449
+ ` ` `
450
+
451
+ And now we can go back to the shell, and try running `ubuntu-frame` :
452
+
453
+ ` ` ` shell
454
+ $SNAP/usr/local/bin/frame
455
+ ` ` `
0 commit comments