Recently I started working with the software simulator for aarch64. Aarch64 is of course the 64 bit architecture.

One thing I very much enjoy is the ability to modify the contents of the file system of the device under test from my stable workstation. When working with ARM SoC systems like an Arndale or a panda, that’s quite simple, just mount the SD card and away you go. For a software simulator environment it’s a bit different.

When you download the file system image for aarch64 from Linaro once gunziped, you have a .img file. This is a disk image with partitions in it. In order to loop back mount it and get at either the boot partition or the root file system you need to resort to a little trick. 

parted  ./vexpress64-openembedded_minimal-armv8_20130423-299.img

(parted) unit
Unit? [B]? B
(parted) print
Model: (file)
Disk /home/tgall/aarch64/vexpress64-openembedded_minimal-armv8_20130423-299.img: 536870912B
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number Start End Size Type File system Flags
1 32256B 54525439B 54493184B primary fat16 boot, lba
2 54525952B 536870911B 482344960B primary ext4

(parted) q

 

So here we have a disk image with two partitions. The system file system is in the second partition and that’s what I want to mount. Using the partition start vaue in bytes and excluding the ‘B’ at the end of the number, we use that number with mount.

 mount -o loop,offset=54525952 -t ext4 ./vexpress64-openembedded_minimal-armv8_20130423-299.img /mnt/aarch-root-filesystem

And there you have it.

linaro-gpgpu mailing list

Posted: April 22, 2013 in Uncategorized

For those interested in general purpose computing on GPUs on ARM SoC devices, we’ve created the linaro-gpgpu mailing list. I don’t anticipate it’ll be a high traffic list. On the list you’ll find discussions and patches for GPGPU implementations such as HSA or OpenCL, open source packages using GPGPU, and modifications to various open source components so that they’ll work better with a GPGPU implementation.

The list can be found at http://lists.linaro.org/mailman/listinfo/linaro-gpgpu

OpenCL on ARM (part 1)

Posted: March 29, 2013 in linaro, OpenCL

A few weeks past before Linaro Connect I had started to see what might be available for OpenCL implementations on ARM. Via a little bit of googling it seemed that the only choice would going to be for boards with a Mali 6xx GPU. This was ok since that basically boils down to the Arndale board and the Samsung Chromebook. Both good options since I happened to have a Chromebook.

I downloaded the Mali OpenCL SDK which can be found from their site.

It didn’t take long following the instructions when I realized the SDK isn’t like most SDKs. Not contained within this SDK was any form of Mali OpenCL driver. Within the Mali SDK it contains a lib directory which when you type make (and you probably have to fix their Makefile to make it work) it will yield a libOpenCL.so it’s just that it’s essentially an empty stub library. You can compile and link against what is provided but when you try and run nothing will happen. Within this library is just a long list of functions with no implementation behind it. None. Not very useful.

Via this discussion, at the very bottom we see a bit of an explanation as to why.

We (ARM) do provide a build of Linux containing the OpenCL driver to select partners under a specific license, but this is not public at this time

So they leave it to the maker of the board to at their open distribute a driver. This gives the board maker the option to not support OpenCL at all if they so choose. Ok, I respect that and it makes sense, since just because a Mali T6xx part is on a board doesn’t mean that it’s wired up universally the same way which may require some driver specific change. It’s conjecture on my part since obviously we’ve no view into the source code as it’s not Open Source.

That said, the Insignal discussion can be found on their boards here. Simply put, not yet available for Linux but supposedly available for their Android Jelly Bean.

Hrumph!

I like Android but the problem is at Connect I gave up my Arndale board to one of my coworkers. I haven’t ordered a new one since the wait times are impressively long and currently they are sold out again at HowChip.

Android to my knowledge doesn’t run on the ARM based Samsung Chromebook so I’m out of options.

Next I did a little splunking within the ChromeOS file system on my Chromebook to see if I might find something to suggest that OpenCL was there. I didn’t find libOpenCL.so in any of the usual places so it’s probably safe to say ChromeOS doesn’t make use of OpenCL. No chance of copying over any binaries for use on Linux.

So backing up what other options do I have? Well I do have an OSX option. Putting together an OpenCL HelloWorld there is quite easy. Still.

I’ve a couple Intel Linux boxes, at least it would be a place to get my feet wet in the meantime and be more in line with what OpenCL on ARM linux will be like. So on Ubuntu I proceeded. There are two options. Either Intel’s VCSource or AMD’s APP SDK both proclaiming OpenCL support.

Let’s talk about how the OpenCL infrastructure is installed. First the includes that are best placed at /usr/include/CL. Not needed of course for runtime. Next if you put the contents of each respective SDK’s lib directory into /usr/lib/OpenCL/vendor/  intel or amd then you can have both SDK’s installed at the same time. These are needed at runtime. Next you have /etc/OpenCL/vendors which will have a number of .icd files. You only need one but with multiple SDKs you’ll have more than one.  The ICD is Installable Client Driver. IE This points to the real driver. This is required at runtime. For libOpenCL.so it looks to the icd to specify which driver(s) to use making libOpenCL.so more of a traffic cop between your application that uses libOpenCL.so and the real driver. Next within /etc/ld.so.conf.d you’ll have a new file that points to where the shared libraries are. So in my case these point to /usr/lib/OpenCL/vendors/intel and /usr/lib/OpenCL/vendors/amd in separate files. Last I have symlinks for OpenCL.so OpenCL.so.1 and OpenCL.so.1.2 that all point into the libOpenCL.so implementation I’m using such as the one in /usr/lib/OpenCL/vendors/amd.

AMD’s APP wants to set the environment variable AMDAPPSDKROOT=”/opt/AMDAPP” and does so in /etc/profile.

So knowing these aspects of setup, I proceeded to try out a simple HelloWorld app that would get the list of devices, create a context and spawn off some simple work to validation things are sane.

Let’s talk about how well things work with the Intel and AMD SDKs.

Intel’s SDK for Linux indicates they only support a limited set of CPUs. GPUs are not supported. Neither is the i7 CPU which is what my laptop has. Tried to run. Fail!  Intel’s SDK does not support any of their GPUs. If you want to use their SDK with an i7 for instance you can only do so on Windows! Lame! Further why Intel would have a dep on a very limited set of CPUs is beyond me.

Ok so obviously this wasn’t going to work. Next I switched over to the AMD APP SDK. As it turns out they support OpenCL for just CPUs IE without using a GPUs or for submitting work on both CPUs and GPUs. My laptop and my main intel desktop does not have an ATI GPU so this was essential for me to use the AMD implementation since they only support ATI GPUs, and as it turns out “any” Intel based CPU. Using the AMD supplied HelloWorld OpenCL app, it ran. But.

./HelloWorld
Setting of real/effective user Id to 0/0 failed
FATAL: Module fglrx not found.
Error! Fail to load fglrx kernel module! Maybe you can switch to root user to load kernel module directly
No GPU device available.
Choose CPU as default device.
input string:
GdkknVnqkc
output string:
HelloWorld

fglrx of course is the ATI kernel module. Via OpenCL you can specify that your workload is only going to be directed at CPUs. Even tho you might do so you’ll still get this error every time. Awesome! Least as compared to the Intel offering it runs on any CPU.

Adventures with Lava

Posted: March 27, 2013 in Uncategorized

I’ve been enabling piglit/waffle, a large collection of OpenGL, OpenGL ES and OpenCL tests, for running inside of Linaro’s LAVA test farm. The task is not complete yet but it’s coming along nicely. Here’s some things I’ve learned along the way that I believe are useful to pass along.

First some basics. In order to run in the lava farm, you need a token. You obtain a token from validation.linaro.org.

Token in hand, then you need the following components.

  • An OS image to test that is accessable via the net. (Via HTTP seems best)
  • A job description which lives in a json file. This defines what image to load and what test to run.
  • A test description which is in a yaml formatted file. You’ll want to place this test description within a git repo which is accessable via the net.
  • Something to test which has some form of output.

Let’s work through each element and consider some approaches which will make your life easier.

Testing is a job

At the top level is the json format job file. It loads an OS image and runs an identified test. Within this example, it identifies it wants to run on panda hardware, it loads the references Android components which are at the referenced http addresses.

{
 "timeout": 1800,
 "job_name": "piglit-android",
 "device_type" : "panda",
 "actions": [
 {
 "command": "deploy_linaro_android_image",
 "parameters": {
 "data": "http://people.linaro.org/~tomgall/android-panda/userdata.tar.bz2",
 "boot": "http://people.linaro.org/~tomgall/android-panda/boot.tar.bz2",
 "system": "http://people.linaro.org/~tomgall/android-panda/system.tar.bz2"
 }
 },
 {
 "command": "android_install_binaries"
 },
 {
 "command": "lava_test_shell",
 "parameters": {
 "testdef_repos": [
 {"git-repo": "git://git.linaro.org/people/tomgall/test-definitions.git",
 "testdef": "android/shader_runner_gles2.yaml"
 }],
 "timeout": 600
 }
 },
 {
 "command": "submit_results_on_host",
 "parameters": {
 "stream": "/anonymous/tom-gall/",
 "server": "http://validation.linaro.org/lava-server/RPC2/"
 }
 }
 ]
}

Don’t create a yaml test file for each individual test found in a whole mass collection of tests, be lazy, try to run as many tests in one shot as makes sense. You’ll be happier otherwise you’ll have a boatload of yaml test files to create. That’s to fun to create (even to script) or maintain.

Remember for each yaml file there will be a step to install the OS image, install the test, run the test and then restore the machine back to what it was. So keeping the number of yaml files more to a reasonable number is a wise use of resources.

Within this json file, there are several things to pay attention to. Within the lava_test_shell, I instruct that I want lava to pull from my git repo and from within that git repo to use the android/shader_runner_gles2.yaml file to run. This gets us to the next layer in the onion.

Notice the time out values. There is no magic here. Unfortunately since it’s a little hard to tell if a test run has gone off into the weeds, Lava uses a timer (in seconds) which if passed, causes Lava to bonk the system under test over the head, reboot and install back to a last good known state making it ready for the next testing to come along.

Also look at the submit_results_on_host part. You’ll have your own obviously which is tied to your id. This gives the test an ability via a series of URLs to allow you to get at the results.

 

android/shader_runner_gles2.yaml

metadata:
 name: shader_runner_gles2
 version: 1.0 
 format: "Lava-Test-Shell Test Definition 1.0"
install:
 git-repos:
 - git://git.linaro.org/people/tomgall/test-definitions.git
run:
 steps:
 - "export PIGLIT_PLATFORM=android"
 - "START_DIR=$(pwd)"
 - "cd test-definitions/android/scripts"
 - "./homescreen.sh"
 - "cd $START_DIR"
 - "cd test-definitions/android/scripts"
 - "./piglit-run-shader.sh /system/xbin/piglit/piglit-shader-test/shader_runner_gles2 /data/shader-data"
parse:
 pattern: "(?P<test_case_id>.*-*):\\s+(?P<result>(pass|fail))"
 fixupdict:
 PASS: pass
 FAIL: fail
 SKIP: skip

Within this yaml file we get closer to the testcase we are going to run but we’re not quite there yet. What we have is the git repository again, but in this case it’s going to be installed on the system under test. The run: section is a sequence of commands that will run on our Android system. The homescreen.sh script waits for the homescreen to come up before anything continues on. Since piglit is all graphical in nature we need the boot to have occurred all the way up to the homescreen or we will have lots of failures.

Next we run the piglit-run-shader.sh script which bridges between the Lava world and the piglit world. To this script we pass the test binary to run and a directory where all the shader data is contained. Why?

When in the land of X, do as X does, impedance match between the two universes

Lava has expectations about resulting output. It’s better to use your yaml to call a script and then from that script call your testcase or testcases, interpret the results in the script and then echo out in the format that Lava expects. Let’s look at the piglit-run-shader.sh script

#!/system/bin/sh
# find and loop over the shader tests found
# recursively in the named directory
find ${2} -name *.shader_test -print0 | while read -d $'' file
do
 RESULT=$( ${1} ${file} -auto )
PSTRING="PIGLIT: {'result': 'pass'"
 SSTRING="PIGLIT: {'result': 'skip'"
 FSTRING="PIGLIT: {'result': 'fail'"
case $RESULT in
 *"$PSTRING"*) echo "${file}: pass";;
*"$SSTRING"*) echo "${file}: skip";;
 
 *"$FSTRING"*) echo "${file}: fail";;
*) echo "${file}: fail";;
 esac
done

First notice this is a shell script. The first action is performs is a find on the data file for all the shader_test data files. Then looping over what is found it runs the test program binary that was passed in and with the results, scans it and matches against what piglit outputs in json, then echos out a result in the format that Lava wants. Everybody stays happy.

Running

To run all of this in the lava farm (which is really the easiest way to test it) I use the following command:

lava-tool submit-job https://tom-gall@validation.linaro.org/lava-server/RPC2/ run-glslparser.json

Linaro Connect Asia 2013 was held March 4th – 8th in Hong Kong. 4 of us from the Graphics Working Group were in attendance. I’ve written up our notes and outcomes from the week. They can be found in the Linaro Wiki:

https://wiki.linaro.org/WorkingGroups/Middleware/Graphics/Notes/LCA-2013

We very much look forward to the next Connect which will be in July of this year in Dublin Ireland. Until then, we’ve got some work to do!

Here’s another useful example with the Android build system.

How do you install a number of files in the Android.mk build system without actually specifying the files?

In this case, it makes a single test case that uses lots and lots of data files. Who wants to name each and every data file? I don’t!  I have better things to do! Let’s look at an example:

LOCAL_PATH:= $(call my-dir)
piglit_shared_libs := libGLESv2 \
 libwaffle-1 \
 libpiglitutil_gles2 \
piglit_c_includes := $(piglit_top)/tests/util \
 bionic \
 $(piglit_top)/src \
 external/waffle/include/waffle \
 external/mesa3d/include \
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libGLESv2 libwaffle-1 libpiglitutil_gles2
LOCAL_C_INCLUDES := $(piglit_c_includes)
LOCAL_CFLAGS := -DPIGLIT_USE_WAFFLE -DPIGLIT_USE_OPENGL_ES2 -DPIGLIT_HAS_ANDROID
LOCAL_MODULE_TAGS := eng 
LOCAL_MODULE := glslparsertest_gles2
systemtarball: glslparsertest_gles2
LOCAL_SRC_FILES := glslparsertest.c
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)/piglit/glslparsertest
include $(BUILD_EXECUTABLE)
define all-vert-frag-files-under
$(patsubst ./%,%, \
 $(shell cd $(1) ; \
 find $(2) -name "*.vert" -or -name "*.frag" -and -not -name ".*" -printf "%P\n" ) \
 )
endef
define glsl2_add_test_data
include $(CLEAR_VARS)
LOCAL_SRC_FILES := glsl2/$1
$(warning $(LOCAL_SRC_FILES)) 
LOCAL_MODULE:= $1
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := data
LOCAL_MODULE_PATH:=$(TARGET_OUT_DATA)/glslparser-data/glsl2
datatarball: $1
include $(BUILD_PREBUILT)
endef
glsl2_files := $(call all-vert-frag-files-under, external/piglit/tests/glslparsertest/glsl2)
$(foreach item,$(glsl2_files),$(eval $(call glsl2_add_test_data,$(item))))

Walking you through. all-vert-frag-files-under contains the find which looks for those files.  The next define glsl2_add_test_data creates a BUILD_PREBUILT block for each one of the data files.  After the define, we call the find naming the directory where to look. The line after goes through the contents of glsl2_files which has the list of data files that the find found. It iterates through each entry, passing each $item as a param in the BUILD_PREBUILT block.

Simple as that, but given I couldn’t find any documentation or examples, I thought I’d save you the trouble. Enjoy!

Or how to do some fairly useful things with the Android build system that were not intuitively obvious to me.

I’ve been working with Android a fair amount this week, both the upstream Android Open Source Project sources and the Linaro sources. For both I’ve been getting piglit to build which has required me to construct a number of Android.mk files. In this case, piglit and waffle are the two packages that need to build. Waffle for it’s library and piglit for it’s library, testcases and test case data.

How do you build a number of binaries in a loop using Android’s Android.mk?

I wondered the same. As the google examples go, for each binary you want to build, you need to specify several LOCAL_* values. If you had to do this for each and every test binary in piglit, it’d be quite quite tedious.  Here’s example how to it the easy way:

include $(call all-subdir-makefiles)

LOCAL_PATH:= $(call my-dir)

piglit_top := $(LOCAL_PATH)/../../..
piglit_shared_libs := libGLESv2 libwaffle-1 libpiglitutil_gles2
piglit_c_includes := $(piglit_top)/tests/util \
bionic \
$(piglit_top)/src \
external/waffle/include/waffle \
external/mesa3d/include \

piglit_c_flags := -DPIGLIT_USE_WAFFLE -DPIGLIT_USE_OPENGL_ES2 -DPIGLIT_HAS_ANDROID

module_name = piglit-spec-gles2

define $(module_name)_etc_add_executable
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := $(piglit_shared_libs)
LOCAL_C_INCLUDES := $(piglit_c_includes)
LOCAL_CFLAGS := $(piglit_c_flags)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := tests
LOCAL_MODULE := $1_gles2
systemtarball: $1_gles2
LOCAL_SRC_FILES := $1.c
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)/piglit/$(module_name)
include $(BUILD_EXECUTABLE)
endef

test_names := invalid-es3-queries minmax
$(foreach item,$(test_names),$(eval $(call $(module_name)_etc_add_executable, $(item))))

It’s fairly straightforward once you have the solution but getting there isn’t exactly documented in the google docs from what I could see. So let me talk you through it.

At the top, I have the list of shared libs that will be linked in and the directories that should be searched.

Within define $(module_name)_etc_add_executable are the set of values  we need to specify for each testcase. Observe that $1 is a parameter passed in. We have to keep to a pattern of test_case.c  will end up as name of the test_case binary, but who cares, this is quite acceptable.

Last test_names is the list of all the test cases we’re going to build. Followed last but not least by the loop that iterates over the test case list.

Next. Data!

How do you copy test case user data to the data partition in an Android.mk file?

Again this was something I scratched my head about, looking through the docs, googled often and came up empty. It’s not hard but it’s not necessarily intuitive.

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE:= sanity.shader_test
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := data
LOCAL_MODULE_PATH:=$(TARGET_OUT_DATA)/shader-data/execution
LOCAL_SRC_FILES := sanity.shader_test
userdatatarball: $(LOCAL_MODULE)
include $(BUILD_PREBUILT)

In this example there is but one data file. But I think you can see where it’s going. Combine with the loop example above and things get quite useful.

Some things to point out.  We need BUILD_PREBUILT since we’re not building anything. The LOCAL_SRC_FILES is our list of data. LOCAL_MODULE_PATH is where to install to.  TARGET_OUT_DATA is /data. It will create the directories for you if they don’t exist.

userdatatarball: is rule to make sure that the datafile ends up in the tarball. I couldn’t figure out a way to not have this but perhaps there is a way. I didn’t run across it.

So there you have it. There might be bugs yet. There might be a better more official way. Based on what I figured out this is what works for me.