I Use This!
Very High Activity

News

Analyzed 9 days ago. based on code collected about 1 month ago.
Posted 2 days ago
We've just released Oracle Solaris 11.3 SRU 29. It contains some important security fixes and enhancements. SRU29 is now available from My Oracle Support Doc ID 2045311.1, or via 'pkg update' from the support repository at ... [More] https://pkg.oracle.com/solaris/support . Features included in this SRU include: libdax support on X86 This feature enables the use of DAX query operations on x86 platforms. The ISV and Open Source communities can now develop DAX programs on x86 platforms. The application developed on x86 platforms can be executed on SPARC platform with no modifications and the libdax API will choose DAX operations supported by the platform. The libdax library on x86 uses software emulation and does not require any change in the user developed applications. Oracle VM Server for SPARC has been updated to version 3.5.0.1 For more information including What's New, Bug Fixes, and Known Issues, see Oracle VM Server for SPARC 3.5.0.1 Release Notes. The Java 8, Java 7, and Java 6 packages have been updated. For more information and bugs fixed, see Java 8 Update 162 Release Notes, Java 7 Update 171 Release Notes, and Java 6 Update 181 Release Notes. The SRU also updates the following components which have security fixes: p7zip has been updated to 16.02 Firefox has been updated to 52.6.0esr ImageMagick has been updated to 6.9.9-30 Thunderbird has been updated to 52.6.0 libtiff has been updated to 4.0.9 Wireshark has been updated to 2.4.4 NVIDIA driver has been updated irssi has been updated to 1.0.6 BIND has been updated to 9.10.5-P3   Full details of this SRU can be found in My Oracle Support Doc 2361795.1 For the list of Service Alerts affecting each Oracle Solaris 11.3 SRU, see Important Oracle Solaris 11.3 SRU Issues (Doc ID 2076753.1). [Less]
Posted 2 days ago
I have a secret, so secret that it cannot be whispered without multiple layers of encryption. So secret that it could only be told to the world under a pseudonym -- an alter ego -- except to the closest of friends on a "need to know" basis. So secret ... [More] that this pseudonym only connected to the Internet through Tor, using the Tor Browser Bundle and Tor Messenger to maintain resilience against even the most subtle of identity leaks. So secret that I'll write it on my blog under my real legal name, for all the world to see and criticise: Over the summer I founded the chai project (proof). My goal was to write a free software driver for Midgard GPUs, better known as the Mali T series produced by ARM. Why? Libreboot supports the Rockchip RK3288 chipset, containing a Mali T760 GPU that is unusable without proprietary software. I purchased a laptop1 with this chipset, and thus my work began. I was not the first to free the GPU. Luc Verhaegan, better known by his handle libv, precedes me. His project, Tamil, reverse engineered enough of the command stream2 to display a textured cube at FOSDEM. But the project ceased there due to the pushback; he never released his work. To this day, the source code for Tamil remains only on the hard drive of libv, invisible to the rest of the free software community. Without that source code, Tamil could not enable free graphics acceleration on my own laptop. I was aware of his ill-fated tale. That said, I was not discouraged. My work with the GPU would proceed, only carefully enough to avoid his own fate. For starters, to avoid the risk that a future me would withhold the source code, I published everything from the beginning, immediately as it was written. Thankfully, the source code remains online, downloaded by many others, spread out between several laptops and servers hosted in multiple countries. Retroactive attempts to censor me would inevitably fail thanks to the Streisand effect. The work is safe. My other change was to adopt a pseudonym. By contrast, libv worked under his real name, so when there was alleged retaliation, they knew exactly who to target. His real person was exposed to damage as a result of Tamil. This could be a problem for me: depending on my life aspirations and my personal resilience, to work on this GPU under my real name could pose a threat to me as well. Thus, I, Alyssa Rosenzweig, student, writer, programmer, and artist, did not author the work. Cafe Beverage did. If the project were to come into jeopardy, no harm would come to me. Only my alias cafe was at risk. And at least at first, I was surgically careful to ensure that an outsider could not correlate my two identities. Yet here I am, six months later, proclaiming it for all to hear: I am Cafe Beverage. What changed? I was no longer able to handle the cognitive load of a second persona. Technically, I am well-versed in anonymity software, as an avid user of Tor, GPG, and OTR. But socially and psychologically? Nobody warned me of the mental toll it would take to have to separate myself from, well, myself. To use anonymity technologies passively is easy. When simply browsing the web in peace, merely exercising the anonymous right to read, the only burden is the frustration of the network speed itself. But once you begin to contribute, changing from anonymity to pseudonymity, the complexity balloons. It becomes necessary to scrutinise every little thing you do, in both your pseudonymous and real lives, to ensure that there will be no crossing over whatsoever. There is no golden rule to staying pseudonymous. No, there are dozens of rules, most of which are easy to ignore and difficult to follow. It is nearly impossible to balance it all for anyone not already well-versed in operational security ("opsec"). What types of precautions are needed? The Whonix project maintains a short list of twenty-two basic missteps which compromise your anonymity. They also maintain a specific guide on anonymous "Surfing, Posting, and Blogging" with another endless list of attacks to defend against. There are, of course, the precautions given by the Tor project itself, although really you should read through the entirety of the Tor FAQ -- it's only twenty-one thousand words. Of course, the mind-boggling complexity is warranted. For an activist in a repressive regime, perhaps the archetypical blogger in Iran, these precautions are necessary and hardly enough. For someone in such a situation, the slightest identity slip is lethal. Maintaining full separation of identities is difficult, but when a user's own government is determined to kill dissidents, there are bigger concerns than the cognitive burden of pseudonymity. But for me? For me, there is no risk of physical injury from my research. libv is still alive despite his "secret" being out for years. There are no black bags in my future from publicising who cafe really is. Of course, there is a third option: disappear. Stop using the cafe identity, pretend it never existed, let my nick on IRC expire. The other contributors would not know me well enough to compromise me. I could cease the mental gymnastics. There would be virtually no risk. As far as an observer of my non-anonymous self is concerned, the project never existed. For six months, I chose this option, or rather I succumbed to it. The quantity of my code contributions slowed to a halt; the frequency of my check-ins to IRC faded soon thereafter. At some point, I must have logged in as cafe for the last time, but I do not remember this final milestone. I merely faded into obscurity, until one day I wiped my hard drive during a routine operating system install and lost cafe's passwords. I don't mourn the missing files. But the new year has come. I have switched computers; today, I am using my Libreboot laptop full-time. This post is being written from vim on that very laptop, running only free software. I need the free Midgard GPU drivers more than ever, and I am willing to put in the work to bring them into fruition. So note the pronoun: I will be the one continuing on the project, alongside the awesome folks from the BiOpenly community. Not cafe nor a new pseudonym conjured from mid-air, but I. GPU driver development is difficult enough without the mental juggling associated with creating a person out of nothing. To come out of the shadows brings legitimacy to the project. It will clear up any legal uncertainties surrounding copyright, the complexities of which are amplified when the author of a work is a pseudonym who disappeared. It will allow me to take ownership of my driver work, for instance on a C.V. Most of all, it will allow me to be myself. It will grant me a different type of digital freedom, a familiar breath of fresh air. Coming out as the author of chai is, in many respects, the same as coming out as a queer person. My name is Cafe Beverage. It feels good to write it. An Asus C201 Chromebook made in 2015↩ GPU parlance for the protocol used to interface with the hardware. It is also necessary to reverse engineer the shader binaries, a task which was completed successfully by Connor Abbott↩ [Less]
Posted 2 days ago
whistles -- Nothing to see here, move along kids. Hello, Triangle!
Posted 3 days ago
This is the second part of a series; see the first part for a table of contents.When the basic pattern of having classes with variables that are filled in via template arguments or let-statements reaches the limits of its expressiveness, it can ... [More] become useful to calculate values on the fly. TableGen provides string concatenation out of the box with the paste operator ('#'), and there are built-in functions which can be easily recognized since they start with an exclamation mark, such as !add, !srl, !eq, and !listconcat. There is even an !if-builtin and a somewhat broken and limited !foreach.There is no way of defining new functions, but there is a pattern that can be used to make up for it: classes with ret-values:class extractBit {  bit ret = !and(!srl(val, bitnum), 1);}class Foo {  bit bitFour = extractBit.ret;}def Foo1 : Foo<5>;def Foo2 : Foo<17>;This doesn't actually work in LLVM trunk right now because of the deficiencies around anonymous record instantiations that I mentioned in the first part of the series, but after a lot of refactoring and cleanups, I got it to work reliably. It turns out to be an extremely useful tool.In case you're wondering, this does not support recursion and it's probably better that way. It's possible that TableGen is already accidentally Turing complete, but giving it that power on purpose seems unnecessary and might lead to abuse.Without recursion, a number of builtin functions are required. There has been a !foreach for a long time, and it is a very odd duck:def Defs {  int num;}class Example nums> {  list doubled = !foreach(Defs.num, nums, !add(Defs.num, Defs.num));}def MyNums : Example;In many ways it does what you'd expect, except that having to define a dummy record with a dummy variable in this way is clearly odd and fragile. Until very recently it did not actually support everything you'd think even then, and even with the recent fixes there are plenty of bugs. Clearly, this is how !foreach should look instead:class Example nums> {  list doubled =      !foreach(x, nums, !add(x, x));}def MyNums : Example;... and that's what I've implemented.This ends up being a breaking change (the only one in the whole series, hopefully), but !foreach isn't actually used in upstream LLVM proper anyway, and external projects can easily adapt.A new feature that I have found very helpful is a fold-left operation:class Enumeration items> {  list ret = !foldl([], items, lhs, item,      !listconcat(lhs, [!size(lhs) # ": " # item]));}def MyList : Enumeration;This produces the following record:def MyList {    // Enumeration  list ret = ["0: foo", "1: bar", "2: baz"];  string NAME = ?;}Needless to say, it was necessary to refactor the TableGen tool very deeply to enable this kind of feature, but I am quite happy with how it ended up.The title of this entry is "Functional Programming", and in a sense I lied. Functions are not first-class values in TableGen even with my changes, so one of the core features of functional programming is missing. But that's okay: most of what you'd expect to have and actually need is now available in a consistent manner, even if it's still clunkier than in a "real" programming language. And again: making functions first-class would immediately make TableGen Turing complete. Do we really want that? [Less]
Posted 3 days ago
This is the first entry in an on-going series. Here's a list of all entries: What has TableGen ever done for us? Functional Programming to be continued Anybody who has ever done serious backend work in LLVM has probably developed a love-hate ... [More] relationship with TableGen. At its best it can be an extremely useful tool that saves a lot of manual work. At its worst, it will drive you mad with bizarre crashes, indecipherable error messages, and generally inscrutable failures to understand what you want from it.TableGen is an internal tool of the LLVM compiler framework. It implements a domain-specific language that is used to describe many different kinds of structures. These descriptions are translated to read-only data tables that are used by LLVM during compilation.For example, all of LLVM's intrinsics are described in TableGen files. Additionally, each backend describes its target machine's instructions, register file(s), and more in TableGen files.The unit of description is the record. At its core, a record is a dictionary of key-value pairs. Additionally, records are typed by their superclass(es), and each record can have a name. So for example, the target machine descriptions typically contain one record for each supported instruction. The name of this record is the name of the enum value which is used to refer to the instruction. A specialized backend in the TableGen tool collects all records that subclass the Instruction class and generates instruction information tables that is used by the C++ code in the backend and the shared codegen infrastructure.The main point of the TableGen DSL is to provide an ostensibly convenient way to generate a large set of records in a structured fashion that exploits regularities in the target machine architecture. To get an idea of the scope, the X86 backend description contains ~47k records generated by ~62k lines of TableGen. The AMDGPU backend description contains ~39k records generated by ~24k lines of TableGen.To get an idea of what TableGen looks like, consider this simple example: def Plain {  int x = 5;}class Room {  string Name = name;  string WallColor = "white";}def lobby : Room;multiclass Floor {  let WallColor = color in {    def _left : Room;    def _right : Room;  }}defm first_floor : Floor<1, "yellow">;defm second_floor : Floor<2, "gray">; This example defines 6 records in total. If you have an LLVM build around, just run the above through llvm-tblgen to see them for yourself. The first one has name Plain and contains a single value named x of value 5. The other 5 records have Room as a superclass and contain different values for Name and WallColor.The first of those is the record of name lobby, whose Name value is "Lobby" (note the difference in capitalization) and whose WallColor is "white".Then there are four records with the names first_floor_left, first_floor_right, second_floor_left, and second_floor_right. Each of those has Room as a superclass, but not Floor. Floor is a multiclass, and multiclasses are not classes (go figure!). Instead, they are simply collections of record prototypes. In this case, Floor has two record prototypes, _left and _right. They are instantiated by each of the defm directives. Note how even though def and defm look quite similar, they are conceptually different: one instantiates the prototypes in a multiclass (or several multiclasses), the other creates a record that may or may not have one or more superclasses.The Name value of first_floor_left is "1_left" and its WallColor is "yellow", overriding the default. This demonstrates the late-binding nature of TableGen, which is quite useful for modeling exceptions to an otherwise regular structure: class Foo {  string salutation = "Hi";  string message = salutation#", world!";}def : Foo {  let salutation = "Hello";} The message of the anonymous record defined by the def-statement is "Hello, world!".There is much more to TableGen. For example, a particularly surprising but extremely useful feature are the bit sets that are used to describe instruction encodings. But that's for another time.For now, let me leave you with just one of the many ridiculous inconsistencies in TableGen:class Tag {  int Number = num;}class Test {  int Number1 = Tag<5>.Number;  int Number2 = Tag.Number;  Tag Tag1 = Tag<5>;  Tag Tag2 = Tag;}def : Test<5>;What are the values in the anonymous record? It turns out that Number1 and Number2 are both 5, but Tag1 and Tag2 refer to different records. Tag1 refers to an anonymous record with superclass Tag and Number equal to 5, while Tag2 also refers to an anonymous record, but with the Number equal to an unresolved variable reference.This clearly doesn't make sense at all and is the kind of thing that sometimes makes you want to just throw it all out of the window and build your own DSL with blackjack and Python hooks. The problem with that kind of approach is that even if the new thing looks nicer initially, it'd probably end up in a similarly messy state after another five years.So when I ran into several problems like the above recently, I decided to take a deep dive into the internals of TableGen with the hope of just fixing a lot of the mess without reinventing the wheel. Over the next weeks, I plan to write a couple of focused entries on what I've learned and changed, starting with how a simple form of functional programming should be possible in TableGen. [Less]
Posted 3 days ago
What we're seeing here is a the LED being fully off (albeit with floating clock and data inputs), drawing somewhere between 0.7-1 mA. I was quite surprised to see such a high quiescent current. For the APA102 2020 which has a 20x20mm footprint this ... [More] is somewhat disappointing, not because it is worse than the normal 50x50 APA102 variants, but rather because the small footprint begs for the IC to be used in wearables and other power consumption sensitive applications. Setup So this is the very simple setup I was using. It's nothing fancy; a multimeter set to the mA range, connected between the power supply and the APA102 breakout board I happened to have laying around. [Less]
Posted 4 days ago
Anybody who has ever done serious backend work in LLVM has probably developed a love-hate relationship with TableGen. At its best it can be an extremely useful tool that saves a lot of manual work. At its worst, it will drive you mad with bizarre ... [More] crashes, indecipherable error messages, and generally inscrutable failures to understand what you want from it.TableGen is an internal tool of the LLVM compiler framework. It implements a domain-specific language that is used to describe many different kinds of structures. These descriptions are translated to read-only data tables that are used by LLVM during compilation.For example, all of LLVM's intrinsics are described in TableGen files. Additionally, each backend describes its target machine's instructions, register file(s), and more in TableGen files.The unit of description is the record. At its core, a record is a dictionary of key-value pairs. Additionally, records are typed by their superclass(es), and each record can have a name. So for example, the target machine descriptions typically contain one record for each supported instruction. The name of this record is the name of the enum value which is used to refer to the instruction. A specialized backend in the TableGen tool collects all records that subclass the Instruction class and generates instruction information tables that is used by the C++ code in the backend and the shared codegen infrastructure.The main point of the TableGen DSL is to provide an ostensibly convenient way to generate a large set of records in a structured fashion that exploits regularities in the target machine architecture. To get an idea of the scope, the X86 backend description contains ~47k records generated by ~62k lines of TableGen. The AMDGPU backend description contains ~39k records generated by ~24k lines of TableGen.To get an idea of what TableGen looks like, consider this simple example: def Plain {  int x = 5;}class Room {  string Name = name;  string WallColor = "white";}def lobby : Room;multiclass Floor {  let WallColor = color in {    def _left : Room;    def _right : Room;  }}defm first_floor : Floor<1, "yellow">;defm second_floor : Floor<2, "gray">; This example defines 6 records in total. If you have an LLVM build around, just run the above through llvm-tblgen to see them for yourself. The first one has name Plain and contains a single value named x of value 5. The other 5 records have Room as a superclass and contain different values for Name and WallColor.The first of those is the record of name lobby, whose Name value is "Lobby" (note the difference in capitalization) and whose WallColor is "white".Then there are four records with the names first_floor_left, first_floor_right, second_floor_left, and second_floor_right. Each of those has Room as a superclass, but not Floor. Floor is a multiclass, and multiclasses are not classes (go figure!). Instead, they are simply collections of record prototypes. In this case, Floor has two record prototypes, _left and _right. They are instantiated by each of the defm directives. Note how even though def and defm look quite similar, they are conceptually different: one instantiates the prototypes in a multiclass (or several multiclasses), the other creates a record that may or may not have one or more superclasses.The Name value of first_floor_left is "1_left" and its WallColor is "yellow", overriding the default. This demonstrates the late-binding nature of TableGen, which is quite useful for modeling exceptions to an otherwise regular structure: class Foo {  string salutation = "Hi";  string message = salutation#", world!";}def : Foo {  let salutation = "Hello";} The message of the anonymous record defined by the def-statement is "Hello, world!".There is much more to TableGen. For example, a particularly surprising but extremely useful feature are the bit sets that are used to describe instruction encodings. But that's for another time.For now, let me leave you with just one of the many ridiculous inconsistencies in TableGen:class Tag {  int Number = num;}class Test {  int Number1 = Tag<5>.Number;  int Number2 = Tag.Number;  Tag Tag1 = Tag<5>;  Tag Tag2 = Tag;}def : Test<5>;What are the values in the anonymous record? It turns out that Number1 and Number2 are both 5, but Tag1 and Tag2 refer to different records. Tag1 refers to an anonymous record with superclass Tag and Number equal to 5, while Tag2 also refers to an anonymous record, but with the Number equal to an unresolved variable reference.This clearly doesn't make sense at all and is the kind of thing that sometimes makes you want to just throw it all out of the window and build your own DSL with blackjack and Python hooks. The problem with that kind of approach is that even if the new thing looks nicer initially, it'd probably end up in a similarly messy state after another five years.So when I ran into several problems like the above recently, I decided to take a deep dive into the internals of TableGen with the hope of just fixing a lot of the mess without reinventing the wheel. Over the next weeks, I plan to write a couple of focused entries on what I've learned and changed, starting with how a simple form of functional programming should be possible in TableGen. [Less]
Posted 8 days ago
When I designed virgl I added a capability system to pass some info about the host GL to the guest driver along the lines of gallium caps. The design was at the virtio GPU level you have a number of capsets each of which has a max version and max ... [More] size.The virgl capset is capset 1 with max version 1 and size 308 bytes.Until now we've happily been using version 1 at 308 bytes. Recently we decided we wanted to have a v2 at 380 bytes, and the world fell apart.It turned out there is a bug in the guest kernel driver, it asks the host for a list of capsets and allows guest userspace to retrieve from it. The guest userspace has it's own copy of the struct.The flow is:Guest mesa driver gives kernel a caps struct to fill out for capset 1.Kernel driver asks the host over virtio for latest capset 1 info, max size, version.Host gives it the max_size, version for capset 1.Kernel driver asks host to fill out malloced memory of the max_size with thecaps struct.Kernel driver copies the returned caps struct to userspace, using the size of the returned host struct.The bug is the last line, it uses the size of the returned host struct which ends up corrupting the guest in the scenario where the host has a capset 1 v2, size 380, but the host is still running old userspace which understands capset v1, size 308.The 380 bytes gets memcpy over the 308 byte struct and boom.Now we can fix the kernel to not do this, but we can't upgrade every kernel in an existing VM. So if we allow the virglrenderer process to expose a v2 all older sw will explode unless it is also upgraded which isn't really something you want in a VM world.I came up with some virglrenderer workarounds, but due to another bug where qemu doesn't reset virglrenderer when it should, there was no way to make it reliable, and things like kexec old kernel from new kernel would blow up.I decided in the end to bite the bullet and just make capset 2 be a repaired one. Unfortunately this needs patches in all 4 components before it can be used.1) virglrenderer needs to expose capset 2 with the new version/size to qemu.2) qemu needs to allow the virtio-gpu to transfer capset 2 as a virgl capset to the host.3) The kernel on the host needs fixing to make sure we copy the minimum of the host caps and the guest caps into the guest userspace driver, then it needs toprovide a way that guest userspace knows the fixed version is in place.4) The guest userspace needs to check if the guest kernel has the fix, and then query capset 2 first, and fallback to querying capset 1.After talking to a few other devs in virgl land, they pointed out we could probably just never add a new version of capset 2, and grow the struct endlessly.The guest driver would fill out the struct it wants to use with it's copy of default minimum values.It would then call the kernel ioctl to copy over the host caps. The kernel ioctl would copy the minimum size of the host caps and the guest caps.In this case if the host has a 400 byte capset 2, and the guest still only has 380 byte capset 2, the new fields from the host won't get copied into the guest structand it will be fine.If the guest has the 400 byte capset 2, but the host only has the 380 byte capset 2, the guest would preinit the extra 20 bytes with it's default values (0 or whatever) and the kernel would only copy 380 bytes into the start of the 400 bytes and leave the extra bytes alone.Now I just have to got write the patches and confirm it all.Thanks to Stephane at google for creating the patch that showed how broken it was, and to others in the virgl community who noticed how badly it broke old guests! Now to go write the patches... [Less]
Posted 10 days ago
Hi All,First of Thank you to everyone who has been sending me PSR test results, I've received well over a 100 reports!Quite a few testers have reported various issues when enabling PSR, 3 often reported issues are: flickering black screen cursor / ... [More] input lag The Intel graphics team has been working on a number of fixes which make PSR work better in various cases. Note we don't expect this to fix it everywhere, but it should get better and work on more devices in the near future.This is good news, but the bad news is that this means that all the tests people have so very kindly done for me will need to be redone once the new improved PSR code is ready for testing. I will do a new blogpost (and email people who have send me test-reports), when the newPSR code is ready for people to (re-)test (sorry).Regards,Hans [Less]
Posted 10 days ago
zsh: corrupt history file /home/$USER/.zsh_history Most zsh user will have seen the above line at one time or another. And it means that re-using your shell history is no longer possible. Maybe some of it can be recovered, but more than likely ... [More] some has been lost. And even if nothing important has been lost, you probably don't want to spend any time dealing with this. Make zsh maintain a backup Run this snippet in the terminal of your choice. cat <> ~/.zshrc # Backup and restore ZSH history strings ~/.zsh_history | sed ':a;N;$!ba;s/\\\\\n//g' | sort | uniq -u > ~/.zsh_history.backup cat ~/.zsh_history ~/.zsh_history.backup | sed ':a;N;$!ba;s/\\\\\n//g'| sort | uniq > ~/.zsh_history EOT What does this actually do? The snippet … [Less]