Update the NAS to 24.05

Updated Wednesday, Jul 24, 2024

Turns out my NAS is vulnerable to the SSH vulnerability which allows anyone to log into your host with enough time, guaranteed. Dubbed regreSSHion (CVE-2024-6387), it affects a host of different OpenSSH version ranges. If one has OpenSSH 9.8p1 or later, one is totally fine.

Unfortunately, the NAS is still on NixOS 23.11. The NAS remains on NixOS, but all my other devices have been migrated off to Debian Testing. In this brief post, I wanted to describe the toil involved with upgrading this NixOS powered NAS. Some of it is my own PEBKAC fault. Some of it is through well meaning defaults of NixOS. Some of it is just not enough attention to detail. Or as I’ve recently come to discern, too complicated or temperamental for my liking. Maybe this will be entertaining or maybe it will be cringe. My hope is this post encompasses the process of upgrading a NixOS host, warts and all. Sorry for my snide remarks; I’m over the promises of unfettered complexity.

Step 1: nix flake update

I haven’t updated the flakes containing both stable and unstable nixpkgs references in some time. So that’s my first step, before considering the upgrade to 24.04 in earnest. As a result, I need to git pull to ensure my repository is up to date. Whoops, a bit of PEBKAC broke git pull on my setup.

ssh agent mess

Been using keychain for sometime. Here’s the relevant code from my dotfiles (link).

# shellcheck disable=SC1090
[[ -r ${HOME}/.keychain/${HOSTNAME}-sh ]] && . "${HOME}/.keychain/${HOSTNAME}-sh"
# shellcheck disable=SC1090
[[ -r ${HOME}/.keychain/${HOSTNAME}-sh-gpg ]] && . "${HOME}/.keychain/${HOSTNAME}-sh-gpg"

# shellcheck disable=SC2086
eval "$(keychain --eval -q --inherit any --agents ssh,gpg ${keys//\~/$HOME})"

Unfortunately, it seems to break ssh agent forwarding. so I can’t git pull on my NAS without disabling this module. That’s the first friction of the day; getting the dang ole’ thing to git pull correctly. After removing this file from my .bashrc.d/, ssh agent forwarding worked again. That’s a problem for another day.

Okay! Next contention.

nixos-rebuild boot fails with no space left on device

I think this is a super frustrating issue that I’ve ran into on most hosts that I’ve deployed NixOS on. Because nix-build’s error reporting won’t tell you the directory it’s building in, it’s hard to know from the nix log ... incantation nor terminal output what’s the root cause of the error. It comes down the particular invocations in the derivation’s (package’s) build phase. Some will print out an absolute path, some won’t. This loosens the feedback loop… Now I have to monitor indirect metrics, such as disk usage or even strace something to see where it’s writing to.

Today, this costed me an hour of iterating with nixos-rebuild incantations in order to coax grafana to compile. For some reason, I assumed my ZFS Dataset named rpool — which contains /root, /home, and /var — might have been the culprit, so I invested an exorbitant amount of time reconfiguring Loki to clean up old log data, moved a handful of Syncthing folders into another ZFS dataset. As it turned out, that wasn’t the problem at all. A tighter feedback loop could have prevented time wastage here.

Another fix for this is to override the TMPDIR environment variable on the failing build. Or set it in your system.environment attribute set for permanent configuration. Next, you might need to reconfigure the size of /tmp if choosing TMPDIR=/tmp. It’s a tmpfs that resides in memory (and swap), its maximum size is configured to a percentage of your physical RAM. One can increase this size or migrate /tmp to a filesystem partition on disk. On low memory hosts it’s best off to eschew tmpfs for /tmp and instead set up a filesystem partition. Filesystem caching is pretty good nowadays so it’s not a serious slowdown as one might have tricked into believing.

Back to it: I tried sudo env TMPDIR=/tmp nixos-rebuild boot and lo and behold, the 4GiB tmpfs was insufficient to build Grafana. Shoot. Retried again for maybe the fifth time with sudo env TMPDIR=/var/tmp nixos-rebuild boot. Another thirty minutes later and the build finished successfully. /var/tmp typically lives either on your /var or / filesystem with plenty of space.

Now to reboot and ssh in.

ssh then zfs load-key funkiness

I have it in my notes how to boot my NixOS powered NAS because it’s not exactly natural nor intuitive. First I reboot, then I wait to ssh in, then issue a zfs load-key command to unlock the rpool which contains NixOS, then kill the other zfs load-key command kicked off by the boot sequence, thereby resuming the boot sequence.

winston@silo ~ $ sudo reboot
[sudo] password for winston:
(7s) winston@silo ~ $ # oh yeah, reboot doesn't work :(
winston@silo ~ $ sudo systemctl reboot

Broadcast message from root@silo on pts/8 (Mon 2024-07-08 17:29:16 CDT):

The system will reboot now!

winston@silo ~ $ Connection to silo closed by remote host.
Connection to silo closed.
(5m50s) 255 winston@quasit ~ $ sleep 120;ssh -p2222 root@silo
~ # zfs load-key rpool
Enter passphrase for 'rpool':
~ # pkill zfs  # Next type Return followed by ~. to kill the ssh session!
~ # Connection to silo closed.
(56s) 255 winston@quasit ~ $ sleep 60; ssh -A silo

                           +&-
     Welcome to           _.-^-._    .--.
        silo.          .-'   _   '-. |__|
                      /     |_|     \|  |
                     /               \  |
                    /|     _____     |\ |
                     |    |==|==|    |  |
 |---|---|---|---|---|    |--|--|    |  |
 |---|---|---|---|---|    |==|==|    |  |
^jgs^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Last login: Mon Jul  8 17:23:33 2024 from 10.20.1.44
winston@silo ~ $ systemctl status

After pkill zfs is ran, the ssh connection will become unresponsive. Type return followed by ~. to tell OpenSSH to exit.

Systemd status is “still starting”. So I’ll come back another minute or two, see if it’s happy.

Okay, now it says systemd state is “running” and not “degraded”. We’re in business!

Commit the changes

Now to commit the flake changes:

winston@silo ~/p/nixos-configs $ git commit -m 'flake: refresh'
.git/hooks/pre-commit: line 13: /nix/store/4zqn5lajki1z3a2avia658l1wacpi8v0-pre-commit-3.3.3/bin/pre-commit: No such file or directory
1 winston@silo ~/p/nixos-configs $ pre
precat      preunzip    prezip      prezip-bin
1 winston@silo ~/p/nixos-configs $ nix run nixpkgs#pre-commit install
pre-commit installed at .git/hooks/pre-commit
winston@silo ~/p/nixos-configs $ git commit -m 'flake: refresh'
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
Check Yaml...........................................(no files to check)Skipped
Check for added large files..............................................Passed
[master f0be2ea] flake: refresh
 2 files changed, 9 insertions(+), 8 deletions(-)

Yes, I know pre-commit should exist in my environment.systemPackages. I forgot why I didn’t add it. Maybe pre-commit is supposed to be in this folder’s shell.nix? Complicated. You can see why I’m shrinking away from nix-powered workflows! I just want the thing to do the thing.

Now, on to the upgrade to fix the OpenSSH vulnerability. A couple hours later…

Re-read the release notes

NixOS has this stance about upgrades not dissimilar to classical stable release distros. Things will break. Things will break in fantastic ways. just don’t upgrade, and things won’t break. It’s a white lie of NixOS: that somehow you enjoy stability between upgrades. You aren’t guaranteed stability between upgrades. You must possesses the same due diligence and best judgment that is expected on any other distro. Be sure to read the release notes, there is no time-efficient alternative. A poorly aged adage of NixOS is “roll back if upgrade breaks stuff”. No need to ensure most upgrades go well on first try if that’s the community spirit of releasing upgrades! And don’t get me started on what happens if you need security updates. This blog post happens — you must upgrade everything or suture nixpkgs in order to recoup security updates.

Back to it. As promised, I read the release notes and my biggest take away is that there is an upgrade to Loki 3.0.0. I’m okay with Loki breaking, so I won’t bother with it until I experience breakage. It appears that my Nextcloud is still supported, so I won’t struggle through a Nextcloud upgrade (yet).

Edit the flake inputs

All I did was modify inputs.nixpkgs.url to point to github:NixOS/nixpkgs/release-24.05. Then I ran nix flake update.

winston@silo ~/p/nixos-configs $ nix flake update
warning: Git tree '/home/winston/p/nixos-configs' is dirty
warning: updating lock file '/home/winston/p/nixos-configs/flake.lock':
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/7144d6241f02d171d25fba3edeaf15e0f2592105' (2024-07-02)
  → 'github:NixOS/nixpkgs/de429c2a20520e0f81a1fd9d2677686a68cae739' (2024-07-08)
• Updated input 'unstable':
    'github:NixOS/nixpkgs/9f4128e00b0ae8ec65918efeba59db998750ead6' (2024-07-03)
  → 'github:NixOS/nixpkgs/655a58a72a6601292512670343087c2d75d859c1' (2024-07-08)
warning: Git tree '/home/winston/p/nixos-configs' is dirty

Next it’s time to try to build it, remembering to point TMPDIR to the spacious /var/tmp.

Breaking pineentry change

winston@silo ~/p/nixos-configs $ sudo env TMPDIR=/var/tmp nixos-rebuild boot --flake ~/p/nixos-configs# --impure
[sudo] password for winston:
warning: Git tree '/home/winston/p/nixos-configs' is dirty
building the system configuration...
warning: Git tree '/home/winston/p/nixos-configs' is dirty
error:
       … while calling the 'head' builtin

         at /nix/store/xyqsyg4nw57nbva6r339hf5223d0ar4r-source/lib/attrsets.nix:1575:11:

         1574|         || pred here (elemAt values 1) (head values) then
         1575|           head values
             |           ^
         1576|         else

       … while evaluating the attribute 'value'

         at /nix/store/xyqsyg4nw57nbva6r339hf5223d0ar4r-source/lib/modules.nix:809:9:

          808|     in warnDeprecation opt //
          809|       { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
             |         ^
          810|         inherit (res.defsFinal') highestPrio;

       (stack trace truncated; use '--show-trace' to show the full trace)

       error:
       Failed assertions:
       - The option definition `programs.gnupg.agent.pinentryFlavor' in `/nix/store/g4py9g5mqznfzgn7nrz1glg811k9xpll-source/common/base.nix' no longer has any effect; please remove it.
       Use programs.gnupg.agent.pinentryPackage instead
       (28s) 1 winston@silo ~/p/nixos-configs $

Balls. Legacy code shims be damned, this is NixOS! I think I need to edit some configuration, because the powers that be decided it must be done. But where? Cool errors bro. No problem, can search my source tree and with any hope, it’s within my own Nix configuration, and not in another input (e.g. the nixpkgs flake):

winston@silo ~/p/nixos-configs $ rg pinentryFlavor
common/base.nix
54:    pinentryFlavor = "gtk2";

Oh maybe I could have taken the /nix/store/not-the-path-that-im-working-out-of-prefix-source/common/base.nix path suffix and visited the relative path common/base.nix. Icky to manually fix paths in error messages, but that should suffice next time!

Okay, deleted the offending line. I don’t know why I’m using gtk2 the flavor anymore, so maybe it’s not important… let’s pray that it wasn’t important!

winston@silo ~/p/nixos-configs $ sudo env TMPDIR=/var/tmp nixos-rebuild boot --flake ~/p/nixos-configs# --impure
[sudo] password for winston:
warning: Git tree '/home/winston/p/nixos-configs' is dirty
building the system configuration...
warning: Git tree '/home/winston/p/nixos-configs' is dirty
error:
       … while calling the 'head' builtin

         at /nix/store/xyqsyg4nw57nbva6r339hf5223d0ar4r-source/lib/attrsets.nix:1575:11:

         1574|         || pred here (elemAt values 1) (head values) then
         1575|           head values
             |           ^
         1576|         else

       … while evaluating the attribute 'value'

         at /nix/store/xyqsyg4nw57nbva6r339hf5223d0ar4r-source/lib/modules.nix:809:9:

          808|     in warnDeprecation opt //
          809|       { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
             |         ^
          810|         inherit (res.defsFinal') highestPrio;

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: Package ‘nextcloud-27.1.11’ in /nix/store/xyqsyg4nw57nbva6r339hf5223d0ar4r-source/pkgs/servers/nextcloud/default.nix:35 is marked as insecure, refusing to evaluate.


       Known issues:
        - Nextcloud version 27.1.11 is EOL

       You can install it anyway by allowing this package, using the
       following methods:

       a) To temporarily allow all insecure packages, you can use an environment
          variable for a single invocation of the nix tools:

            $ export NIXPKGS_ALLOW_INSECURE=1

          Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake,
                then pass `--impure` in order to allow use of environment variables.

       b) for `nixos-rebuild` you can add ‘nextcloud-27.1.11’ to
          `nixpkgs.config.permittedInsecurePackages` in the configuration.nix,
          like so:

            {
              nixpkgs.config.permittedInsecurePackages = [
                "nextcloud-27.1.11"
              ];
            }

       c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
          ‘nextcloud-27.1.11’ to `permittedInsecurePackages` in
          ~/.config/nixpkgs/config.nix, like so:

            {
              permittedInsecurePackages = [
                "nextcloud-27.1.11"
              ];
            }
(28s) 1 winston@silo ~/p/nixos-configs $

Oh crud, apparently I’m running an insecure Nextcloud? Who knew! Looks like one can set an environment variable (NIXPKGS_ALLOW_INSECURE=1) to tell nixos-rebuild to calm down if only a smidgen.

Loki changes

The release notes did mention Loki configuration changed and advised that users read the upstream Loki release notes too. It looks like I can’t push the Loki upgrade back and must handle it now:

winston@silo ~/p/nixos-configs $ sudo env NIXPKGS_ALLOW_INSECURE=1 TMPDIR=/var/tmp nixos-rebuild boot --flake ~/p/nixos-configs# --impure
warning: Git tree '/home/winston/p/nixos-configs' is dirty
building the system configuration...
warning: Git tree '/home/winston/p/nixos-configs' is dirty
error: builder for '/nix/store/v6g5b5c383a4h6i8bl210h91cp54qpz6-validate-loki-conf.drv' failed with exit code 1;
       last 5 log lines:
       > failed parsing config: /nix/store/3i7y6y5nwjqz8mhg1kakhmyd1cv7cy3i-loki-config.json: yaml: unmarshal errors:
       >   line 4: field max_look_back_period not found in type config.ChunkStoreConfig
       >   line 13: field shared_store not found in type compactor.Config
       >   line 31: field max_transfer_retries not found in type ingester.Config
       >   line 59: field shared_store not found in type boltdb.IndexCfg. Use `-config.expand-env=true` flag if you want to expand environment variables in your config file
       For full logs, run 'nix log /nix/store/v6g5b5c383a4h6i8bl210h91cp54qpz6-validate-loki-conf.drv'.
error: 1 dependencies of derivation '/nix/store/cxpdszil18wj6hb3az3jwqbyfy43wmj6-unit-loki.service.drv' failed to build
error: 1 dependencies of derivation '/nix/store/gyh8mr8sqk1gk20qldp062zym2mdy06c-system-units.drv' failed to build
error: 1 dependencies of derivation '/nix/store/qr88n0970ji783bkdwhk8ig7wazksa9v-etc.drv' failed to build
error: 1 dependencies of derivation '/nix/store/p36ja5jhi7wr2ayzxgf7ykkxhss599n2-nixos-system-silo-24.05.20240708.de429c2.drv' failed to build
(3m46s) 1 winston@silo ~/p/nixos-configs $

That list of Loki-specific configuration errors is extremely helpful. Well done. The nixos-rebuild process printed the problematic configuration fields out to the terminal. After trying to make heads or tails of the upgrade guide, I instead merely removed every offending line. Let’s see what works (shrug).

error: builder for '/nix/store/rkmm8wa8vz576bhwpz0wwmv8ck31653j-validate-loki-conf.drv' failed with exit code 1;
       last 1 log lines:
       > level=error ts=2024-07-08T23:14:46.302638345Z caller=main.go:66 msg="validating config" err="MULTIPLE CONFIG ERRORS FOUND, PLEASE READ CAREFULLY\nCONFIG ERROR: invalid compactor config: compactor.delete-request-store should be configured when retention is enabled\nCONFIG ERROR: schema v13 is required to store Structured Metadata and use native OTLP ingestion, your schema version is v11. Set `allow_structured_metadata: false` in the `limits_config` section or set the command line argument `-validation.allow-structured-metadata=false` and restart Loki. Then proceed to update to schema v13 or newer before re-enabling this config, search for 'Storage Schema' in the docs for the schema update procedure\nCONFIG ERROR: `tsdb` index type is required to store Structured Metadata and use native OTLP ingestion, your index type is `boltdb-shipper` (defined in the `store` parameter of the schema_config). Set `allow_structured_metadata: false` in the `limits_config` section or set the command line argument `-validation.allow-structured-metadata=false` and restart Loki. Then proceed to update the schema to use index type `tsdb` before re-enabling this config, search for 'Storage Schema' in the docs for the schema update procedure"
       For full logs, run 'nix log /nix/store/rkmm8wa8vz576bhwpz0wwmv8ck31653j-validate-loki-conf.drv'.

Here’s the error in reformatted:

MULTIPLE CONFIG ERRORS FOUND, PLEASE READ CAREFULLY
CONFIG ERROR: invalid compactor config: compactor.delete-request-store should
              be configured when retention is enabled
CONFIG ERROR: schema v13 is required to store Structured Metadata and use
              native OTLP ingestion, your schema version is v11. Set
              `allow_structured_metadata: false` in the `limits_config`
              section or set the command line argument
              `-validation.allow-structured-metadata=false` and restart Loki.
              Then proceed to update to schema v13 or newer before re-enabling
              this config, search for 'Storage Schema' in the docs for the
              schema update procedure
CONFIG ERROR: `tsdb` index type is required to store Structured Metadata and
              use native OTLP ingestion, your index type is `boltdb-shipper`
              (defined in the `store` parameter of the schema_config). Set
              `allow_structured_metadata: false` in the `limits_config` section
              or set the command line argument
              `-validation.allow-structured-metadata=false` and restart Loki.
              Then proceed to update the schema to use index type `tsdb`
              before re-enabling this config, search for 'Storage Schema'
              in the docs for the schema update procedure

Okay, I’ve added allowed_structured_metadata= false; now what will break next?

CONFIG ERROR: invalid compactor config: compactor.delete-request-store should
              be configured when retention is enabled

OK, I’ve added delete_request_store = "filesystem";, as per this GitHub issue.

It built!

Hooray! It built!

winston@silo ~/p/nixos-configs $ sudo env NIXPKGS_ALLOW_INSECURE=1 TMPDIR=/var/tmp nixos-rebuild boot --flake ~/p/nixos-configs# --impure
warning: Git tree '/home/winston/p/nixos-configs' is dirty
building the system configuration...
warning: Git tree '/home/winston/p/nixos-configs' is dirty
trace: warning: The option `services.nextcloud.extraOptions' defined in `/nix/store/d99kz3ifvz1hqg8wni0bi2j08n3rdisr-source/hosts/silo' has been renamed to `services.nextcloud.settings'.
trace: warning: The option `services.nextcloud.config.defaultPhoneRegion' defined in `/nix/store/d99kz3ifvz1hqg8wni0bi2j08n3rdisr-source/hosts/silo' has been renamed to `services.nextcloud.settings.default_phone_region'.
trace: warning: A legacy Nextcloud install (from before NixOS 24.05) may be installed.

After nextcloud27 is installed successfully, you can safely upgrade
to 28. The latest version available is Nextcloud29.

Please note that Nextcloud doesn't support upgrades across multiple major versions
(i.e. an upgrade from 16 is possible to 17, but not 16 to 18).

The package can be upgraded by explicitly declaring the service-option
`services.nextcloud.package`.

updating GRUB 2 menu...
installing the GRUB 2 boot loader on /dev/disk/by-id/ata-CT120BX500SSD1_1943E3D1AC4B...
Installing for i386-pc platform.
Installation finished. No error reported.
updating GRUB 2 menu...
installing the GRUB 2 boot loader on /dev/disk/by-id/ata-CT120BX500SSD1_1943E3D1AC45...
Installing for i386-pc platform.
Installation finished. No error reported.
(51s) winston@silo ~/p/nixos-configs $

Now to snapshot everything real quick…

winston@silo ~/p/nixos-configs $ sudo zfs snapshot -r naspool@2024-08-07_pre-reboot
winston@silo ~/p/nixos-configs $ sudo zfs snapshot -r rpool@2024-08-07_pre-reboot

Now let’s reboot and hope for the best.

degraded - libvirt-guests.service failure

systemctl status says the state is “degraded”. Let’s see what broke:

winston@silo ~ $ systemctl list-units --failed
  UNIT                   LOAD   ACTIVE SUB    DESCRIPTION
● libvirt-guests.service loaded failed failed libvirt guests suspend/resume service

Legend: LOAD   → Reflects whether the unit definition was properly loaded.
        ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
        SUB    → The low-level unit activation state, values depend on unit type.

1 loaded units listed.
(34s) 3 winston@silo ~ $

OK let’s check the specific service:

winston@silo ~ $ systemctl status libvirt-guests.service
× libvirt-guests.service - libvirt guests suspend/resume service
     Loaded: loaded (/etc/systemd/system/libvirt-guests.service; enabled; preset: enabled)
    Drop-In: /nix/store/70x3p9hhrm202n3lfl1p79bv0h2c59zi-system-units/libvirt-guests.service.d
             └─overrides.conf
     Active: failed (Result: exit-code) since Mon 2024-07-08 18:38:25 CDT; 3min 11s ago
       Docs: man:libvirt-guests(8)
             https://libvirt.org/
    Process: 2340 ExecStart=/nix/store/6a5lmp5p08n9qsfd0l9aqc7jhigm82j9-libvirt-10.0.0/libexec/libvirt-guests.sh start (code=exited, status=1/FAILURE)
   Main PID: 2340 (code=exited, status=1/FAILURE)
         IP: 0B in, 0B out
        CPU: 184ms

Jul 08 18:38:17 silo systemd[1]: Starting libvirt guests suspend/resume service...
Jul 08 18:38:24 silo libvirt-guests.sh[3307]: Resuming guests on default URI...
Jul 08 18:38:25 silo libvirt-guests.sh[3313]: Resuming guest seedbox:
Jul 08 18:38:25 silo libvirt-guests.sh[3318]: error: Failed to start domain 'seedbox'
Jul 08 18:38:25 silo libvirt-guests.sh[3318]: error: operation failed: guest CPU doesn't match specification: extra features: vmx-ins-outs,vmx-true-ctls,vmx-store-lma,vmx-activity-hlt,vmx-vmwrite-vmexit-fields,vmx-apicv-xapic,vmx-ept,vmx-desc-exit,vmx-rdtscp-exit,vmx-apicv-x2apic,vmx-vpid,vmx-wbinvd-exit,vmx-unrestricted-guest,vmx-rdrand-exit,vmx-invpcid-exit,vmx-vmfunc,vmx-shadow-vmcs,vmx-invvpid,vmx-invvpid-single-addr,vmx-invvpid-all-context,vmx-ept-execonly,vmx-page-walk-4,vmx-ept-2mb,vmx-ept-1gb,vmx-invept,vmx-eptad,vmx-invept-single-context,vmx-invept-all-context,vmx-intr-exit,vmx-nmi-exit,vmx-vnmi,vmx-preemption-timer,vmx-vintr-pending,vmx-tsc-offset,vmx-hlt-exit,vmx-invlpg-exit,vmx-mwait-exit,vmx-rdpmc-exit,vmx-rdtsc-exit,vmx-cr3-load-noexit,vmx-cr3-store-noexit,vmx-cr8-load-exit,vmx-cr8-store-exit,vmx-flexpriority,vmx-vnmi-pending,vmx-movdr-exit,vmx-io-exit,vmx-io-bitmap,vmx-mtf,vmx-msr-bitmap,vmx-monitor-exit,vmx-pause-exit,vmx-secondary-ctls,vmx-exit-nosave-debugctl,vmx-exit-load-perf-global-ctrl,vmx-exit-ack-intr,vmx-exit-save-pat,vmx-exit-load-pat,vmx-exit-save-efer,vmx-exit-load-efer,vmx-exit-save-preemption-timer,vmx-entry-noload-debugctl,vmx-entry-ia32e-mode,vmx-entry-load-perf-global-ctrl,vmx-entry-load-pat,vmx-entry-load-efer,vmx-eptp-switching, missing features: vmx-apicv-register,vmx-apicv-vid,vmx-posted-intr
Jul 08 18:38:25 silo systemd[1]: libvirt-guests.service: Main process exited, code=exited, status=1/FAILURE
Jul 08 18:38:25 silo systemd[1]: libvirt-guests.service: Failed with result 'exit-code'.
Jul 08 18:38:25 silo systemd[1]: Failed to start libvirt guests suspend/resume service.

Oh snap, looks like my virtual machine (VM) for BitTorrent is broken. More specifically, libvirtd failed to resume the VM from saved state (it’s like folding your laptop shut, but for virtual machines). By the way, everything on archive.org is available via BitTorrent. Most Linux distros provide .torrent files too! Hosting torrents for these projects is one low-effort way to help out the community.

Here’s the error reformatted:

error: Failed to start domain 'seedbox'
error: operation failed: guest CPU doesn't match specification: extra features:
       vmx-ins-outs,vmx-true-ctls,vmx-store-lma,vmx-activity-hlt,
       vmx-vmwrite-vmexit-fields,vmx-apicv-xapic,vmx-ept,vmx-desc-exit,
       vmx-rdtscp-exit,vmx-apicv-x2apic,vmx-vpid,vmx-wbinvd-exit,
       vmx-unrestricted-guest,vmx-rdrand-exit,vmx-invpcid-exit,
       vmx-vmfunc,vmx-shadow-vmcs,vmx-invvpid,vmx-invvpid-single-addr,
       vmx-invvpid-all-context,vmx-ept-execonly,vmx-page-walk-4,vmx-ept-2mb,
       vmx-ept-1gb,vmx-invept,vmx-eptad,vmx-invept-single-context,
       vmx-invept-all-context,vmx-intr-exit,vmx-nmi-exit,vmx-vnmi,
       vmx-preemption-timer,vmx-vintr-pending,vmx-tsc-offset,vmx-hlt-exit,
       vmx-invlpg-exit,vmx-mwait-exit,vmx-rdpmc-exit,vmx-rdtsc-exit,
       vmx-cr3-load-noexit,vmx-cr3-store-noexit,vmx-cr8-load-exit,
       vmx-cr8-store-exit,vmx-flexpriority,vmx-vnmi-pending,vmx-movdr-exit,
       vmx-io-exit,vmx-io-bitmap,vmx-mtf,vmx-msr-bitmap,vmx-monitor-exit,
       vmx-pause-exit,vmx-secondary-ctls,vmx-exit-nosave-debugctl,
       vmx-exit-load-perf-global-ctrl,vmx-exit-ack-intr,vmx-exit-save-pat,
       vmx-exit-load-pat,vmx-exit-save-efer,vmx-exit-load-efer,
       vmx-exit-save-preemption-timer,vmx-entry-noload-debugctl,
       vmx-entry-ia32e-mode,vmx-entry-load-perf-global-ctrl,
       vmx-entry-load-pat,vmx-entry-load-efer,vmx-eptp-switching,
       missing features: vmx-apicv-register,vmx-apicv-vid,vmx-posted-intr

Whoops, after a quick google, I encountered this regression. If I run virsh start seedbox, I get a similar error related to vmx. The solution is to either upgrade to 10.2.0 or disable the vmx feature in the guest. vmx is used for nested virtualization that which my guest does not utilize. Sidenote, vmx support is detectable via CPUID which was the topic of my last article.

As I don’t use nested virtualization, I opted to disable it. I invoked virsh edit seedbox to spawn a text editor with the libvirtd domain’s (guest’s) XML therein, then edited <feature policy='require' name='vmx'/> to <feature policy='disable' name='vmx'/>. That <feature> element can be found nested within the <cpu> element.

I couldn’t help notice had I built this host with Ubuntu, I wouldn’t had experienced this regression, because the updated QEMU has been shipped already. In fact, the maintainers marked this bug as Critical.

OK am I secure now?

winston@silo ~/p/nixos-configs $ echo | nc localhost 22
SSH-2.0-OpenSSH_9.7
Invalid SSH identification string.

Uhhhhhhhhhhhhhhhhhhhhhhhhhh… what?

OK after reading the discourse, it sounds like they didn’t modify the version string to indicate it has been fixed. If I run nix run nixpkgs#vulnix -- -R $(readlink -f $(which ssh)), I get Found no advisories. Excellent!. This feels wrong and bad. Not a resounding “you’re safe!” and a spiffy new version string to back up this claim. No, all I have instead is a random tool claiming it’s all safe and secure. Trust me bro.

And don’t forget the icing on top of the cake: the nixpkgs team deviated from standard operating procedures to backport the security fix to 23.11, despite 23.11’s EOL (End of Life) status, and despite their insistence on everyone upgrade off EOL releases. Had I read one particular forum post, I would have known that it wasn’t necessary to upgrade!

I’m not out of the woods yet, that pesky Nextcloud upgrade is pending. I’ll be sure to share if I broke anything.

The fact remains, had I read the discourse very carefully, I wouldn’t had invested 6 hours today babysitting a NixOS upgrade, since 23.11 received the same OpenSSH vulnerability fix abject to the team’s standard operating procedures. I’ll leave it at that. I don’t want to be unduly negative, but that’s an opportunity cost on everything else one could do with every day’s sacred time.

The upgrade workflow was cool the first time, but at least one time a year, per machine? That sounds like a lot of toilsome drudgery. Plus one must face the inevitable bitrot caused by the behemoth codebase that nixpkgs has ballooned into, dragged down by a contribution system that permits thousands of tickets to go unsatisfied and hundreds of unmerged PRs to stagnate within its churn.

NixOS has its uses, and I believe my uses are too pedestrian for NixOS.

Here’s a few notes on CPUID and /proc/cpuinfo. I made a table for quick reference.

What is CPUID?

On x86 and amd64 CPUs, there is a large swathe of differences in features available to the software. Some CPUs ship with AES encryption support, others ship with virtualization support, almost all ship with a collection of SIMD (single instruction multiple data) instructions. The name of the game is to reduce CPU execution times using specialized instructions. Gratefully, most users don’t need to think about this, credit to all the various code-paths found in their computer software; if your CPU doesn’t support particular instructions, a naive, slower implementation can fill in the gaps.

In other cases, one needs to know in order to configure embedded or low end hardware for efficient operation. When software is tightly coupled to a single sort of computer architecture, many efficiencies can be realized at a cost of software portability. For example, I am writing this article on a Pentium M laptop 20 years past its prime, yet runs modern Linux just-the-same. It can even run Firefox, albeit rather slowly. Discord will load! Part of this feat is attributed to optimizing software specifically for the quirks of this computer’s architecture: an ever-stalling instruction pipeline, a minute cache size, and a low memory environment. CPU feature detection via CPUID for legacy hardware is concerned instead with choosing effecient code paths at primarily compile time. Most of these optimizations come at a cost: the software only runs on this specific machine.

There’s another case where it helps to understand CPUID. Persnickety firmwares covet virtualization CPU support like a it’s going out of fashion. A quick glance at CPUID-derived diagnostics is a rite-of-passage for any troubleshooter. If the virtualization feature isn’t in /proc/cpuinfo, then the firmware disabled it, or the hardware simply doesn’t support virtualization.

How do we determine what features are available at runtime or compile time? Enter the CPUID instruction. This instruction enumerates CPU hardware features available to software. From a developer’s perspective, all you need to do is set the eax register (and ecx in some cases!), then execute the CPUID instruction. See OSDev Wiki and Wikipedia for supplementary information. This is how software can detect existence of speedy features like AVX SIMD or AES acceleration at runtime. Utilities for configuring build environments for generating optimized software use CPUID to detect what sort of code to generate for the target architecture.

There are varying ways for looking up the features present on a x86 or amd64 machine and a few Linux techniques are outlined below. The easiest technique is to look for the flags in /proc/cpuinfo — see docs.

The CPUID Table

With hopes to understand each CPUID feature, I looked for chart of terse and minimal content, just enough to understand what’s what. An online search didn’t find such a chart or table. So here is a tabulated form of tools/arch/x86/kcpuid/cpuid.csv (gitweb) as found in the 6.6.30 kernel tree. The table isn’t exhaustive, but everything you care about is likely listed herein.

LEAF SUBLEAF register_name bits short_name long_description
0 0 EAX 31:0 max_basic_leafs Max input value for supported subleafs
1 0 EAX 3:0 stepping Stepping ID
1 0 EAX 7:4 model Model
1 0 EAX 11:8 family Family ID
1 0 EAX 13:12 processor Processor Type
1 0 EAX 19:16 model_ext Extended Model ID
1 0 EAX 27:20 family_ext Extended Family ID
1 0 EBX 7:0 brand Brand Index
1 0 EBX 15:8 clflush_size CLFLUSH line size (value * 8) in bytes
1 0 EBX 23:16 max_cpu_id Maxim number of addressable logic cpu in this package
1 0 EBX 31:24 apic_id Initial APIC ID
1 0 ECX 0 sse3 Streaming SIMD Extensions 3(SSE3)
1 0 ECX 1 pclmulqdq PCLMULQDQ instruction supported
1 0 ECX 2 dtes64 DS area uses 64-bit layout
1 0 ECX 3 mwait MONITOR/MWAIT supported
1 0 ECX 4 ds_cpl CPL Qualified Debug Store which allows for branch message storage qualified by CPL
1 0 ECX 5 vmx Virtual Machine Extensions supported
1 0 ECX 6 smx Safer Mode Extension supported
1 0 ECX 7 eist Enhanced Intel SpeedStep Technology
1 0 ECX 8 tm2 Thermal Monitor 2
1 0 ECX 9 ssse3 Supplemental Streaming SIMD Extensions 3 (SSSE3)
1 0 ECX 10 l1_ctx_id L1 data cache could be set to either adaptive mode or shared mode (check IA32_MISC_ENABLE bit 24 definition)
1 0 ECX 11 sdbg IA32_DEBUG_INTERFACE MSR for silicon debug supported
1 0 ECX 12 fma FMA extensions using YMM state supported
1 0 ECX 13 cmpxchg16b ‘CMPXCHG16B - Compare and Exchange Bytes’ supported
1 0 ECX 14 xtpr_update xTPR Update Control supported
1 0 ECX 15 pdcm Perfmon and Debug Capability present
1 0 ECX 17 pcid Process-Context Identifiers feature present
1 0 ECX 18 dca Prefetching data from a memory mapped device supported
1 0 ECX 19 sse4_1 SSE4.1 feature present
1 0 ECX 20 sse4_2 SSE4.2 feature present
1 0 ECX 21 x2apic x2APIC supported
1 0 ECX 22 movbe MOVBE instruction supported
1 0 ECX 23 popcnt POPCNT instruction supported
1 0 ECX 24 tsc_deadline_timer LAPIC supports one-shot operation using a TSC deadline value
1 0 ECX 25 aesni AESNI instruction supported
1 0 ECX 26 xsave XSAVE/XRSTOR processor extended states (XSETBV/XGETBV/XCR0)
1 0 ECX 27 osxsave OS has set CR4.OSXSAVE bit to enable XSETBV/XGETBV/XCR0
1 0 ECX 28 avx AVX instruction supported
1 0 ECX 29 f16c 16-bit floating-point conversion instruction supported
1 0 ECX 30 rdrand RDRAND instruction supported
1 0 EDX 0 fpu x87 FPU on chip
1 0 EDX 1 vme Virtual-8086 Mode Enhancement
1 0 EDX 2 de Debugging Extensions
1 0 EDX 3 pse Page Size Extensions
1 0 EDX 4 tsc Time Stamp Counter
1 0 EDX 5 msr RDMSR and WRMSR Support
1 0 EDX 6 pae Physical Address Extensions
1 0 EDX 7 mce Machine Check Exception
1 0 EDX 8 cx8 CMPXCHG8B instr
1 0 EDX 9 apic APIC on Chip
1 0 EDX 11 sep SYSENTER and SYSEXIT instrs
1 0 EDX 12 mtrr Memory Type Range Registers
1 0 EDX 13 pge Page Global Bit
1 0 EDX 14 mca Machine Check Architecture
1 0 EDX 15 cmov Conditional Move Instrs
1 0 EDX 16 pat Page Attribute Table
1 0 EDX 17 pse36 36-Bit Page Size Extension
1 0 EDX 18 psn Processor Serial Number
1 0 EDX 19 clflush CLFLUSH instr
1 0 EDX 21 ds Debug Store
1 0 EDX 22 acpi Thermal Monitor and Software Controlled Clock Facilities
1 0 EDX 23 mmx Intel MMX Technology
1 0 EDX 24 fxsr XSAVE and FXRSTOR Instrs
1 0 EDX 25 sse SSE
1 0 EDX 26 sse2 SSE2
1 0 EDX 27 ss Self Snoop
1 0 EDX 28 hit Max APIC IDs
1 0 EDX 29 tm Thermal Monitor
1 0 EDX 31 pbe Pending Break Enable
4 0 EAX 4:0 cache_type Cache type like instr/data or unified
4 0 EAX 7:5 cache_level Cache Level (starts at 1)
4 0 EAX 8 cache_self_init Cache Self Initialization
4 0 EAX 9 fully_associate Fully Associative cache
4 0 EAX 25:14 max_logical_id Max number of addressable IDs for logical processors sharing the cache
4 0 EAX 31:26 max_phy_id Max number of addressable IDs for processors in phy package
4 0 EBX 11:0 cache_linesize Size of a cache line in bytes
4 0 EBX 21:12 cache_partition Physical Line partitions
4 0 EBX 31:22 cache_ways Ways of associativity
4 0 ECX 31:0 cache_sets Number of Sets - 1
4 0 EDX 0 c_wbinvd 1 means WBINVD/INVD is not ganranteed to act upon lower level caches of non-originating threads sharing this cache
4 0 EDX 1 c_incl Whether cache is inclusive of lower cache level
4 0 EDX 2 c_comp_index Complex Cache Indexing
5 0 EAX 15:0 min_mon_size Smallest monitor line size in bytes
5 0 EBX 15:0 max_mon_size Largest monitor line size in bytes
5 0 ECX 0 mwait_ext Enum of Monitor-Mwait extensions supported
5 0 ECX 1 mwait_irq_break Largest monitor line size in bytes
5 0 EDX 3:0 c0_sub_stats Number of C0* sub C-states supported using MWAIT
5 0 EDX 7:4 c1_sub_stats Number of C1* sub C-states supported using MWAIT
5 0 EDX 11:8 c2_sub_stats Number of C2* sub C-states supported using MWAIT
5 0 EDX 15:12 c3_sub_stats Number of C3* sub C-states supported using MWAIT
5 0 EDX 19:16 c4_sub_stats Number of C4* sub C-states supported using MWAIT
5 0 EDX 23:20 c5_sub_stats Number of C5* sub C-states supported using MWAIT
5 0 EDX 27:24 c6_sub_stats Number of C6* sub C-states supported using MWAIT
5 0 EDX 31:28 c7_sub_stats Number of C7* sub C-states supported using MWAIT
6 0 EAX 0 dig_temp Digital temperature sensor supported
6 0 EAX 1 turbo Intel Turbo Boost
6 0 EAX 2 arat Always running APIC timer
6 0 EAX 4 pln Power limit notifications supported
6 0 EAX 5 ecmd Clock modulation duty cycle extension supported
6 0 EAX 6 ptm Package thermal management supported
6 0 EAX 7 hwp HWP base register
6 0 EAX 8 hwp_notify HWP notification
6 0 EAX 9 hwp_act_window HWP activity window
6 0 EAX 10 hwp_energy HWP energy performance preference
6 0 EAX 11 hwp_pkg_req HWP package level request
6 0 EAX 13 hdc HDC base registers supported
6 0 EAX 14 turbo3 Turbo Boost Max 3.0
6 0 EAX 15 hwp_cap Highest Performance change supported
6 0 EAX 16 hwp_peci HWP PECI override is supported
6 0 EAX 17 hwp_flex Flexible HWP is supported
6 0 EAX 18 hwp_fast Fast access mode for the IA32_HWP_REQUEST MSR is supported
6 0 EAX 20 hwp_ignr Ignoring Idle Logical Processor HWP request is supported
6 0 EBX 3:0 therm_irq_thresh Number of Interrupt Thresholds in Digital Thermal Sensor
6 0 ECX 0 aperfmperf Presence of IA32_MPERF and IA32_APERF
6 0 ECX 3 energ_bias Performance-energy bias preference supported
7 0 EBX 0 fsgsbase RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE supported
7 0 EBX 1 tsc_adjust TSC_ADJUST MSR supported
7 0 EBX 2 sgx Software Guard Extensions
7 0 EBX 3 bmi1 BMI1
7 0 EBX 4 hle Hardware Lock Elision
7 0 EBX 5 avx2 AVX2
7 0 EBX 7 smep Supervisor-Mode Execution Prevention
7 0 EBX 8 bmi2 BMI2
7 0 EBX 9 rep_movsb Enhanced REP MOVSB/STOSB
7 0 EBX 10 invpcid INVPCID instruction
7 0 EBX 11 rtm Restricted Transactional Memory
7 0 EBX 12 rdt_m Intel RDT Monitoring capability
7 0 EBX 13 depc_fpu_cs_ds Deprecates FPU CS and FPU DS
7 0 EBX 14 mpx Memory Protection Extensions
7 0 EBX 15 rdt_a Intel RDT Allocation capability
7 0 EBX 16 avx512f AVX512 Foundation instr
7 0 EBX 17 avx512dq AVX512 Double and Quadword AVX512 instr
7 0 EBX 18 rdseed RDSEED instr
7 0 EBX 19 adx ADX instr
7 0 EBX 20 smap Supervisor Mode Access Prevention
7 0 EBX 21 avx512ifma AVX512 Integer Fused Multiply Add
7 0 EBX 23 clflushopt CLFLUSHOPT instr
7 0 EBX 24 clwb CLWB instr
7 0 EBX 25 intel_pt Intel Processor Trace instr
7 0 EBX 26 avx512pf Prefetch
7 0 EBX 27 avx512er AVX512 Exponent Reciproca instr
7 0 EBX 28 avx512cd AVX512 Conflict Detection instr
7 0 EBX 29 sha Intel Secure Hash Algorithm Extensions instr
7 0 EBX 30 avx512bw AVX512 Byte & Word instr
7 0 EBX 31 avx512vl AVX512 Vector Length Extentions (VL)
7 0 ECX 0 prefetchwt1 X
7 0 ECX 1 avx512vbmi AVX512 Vector Byte Manipulation Instructions
7 0 ECX 2 umip User-mode Instruction Prevention
7 0 ECX 3 pku Protection Keys for User-mode pages
7 0 ECX 4 ospke CR4 PKE set to enable protection keys
7 0 ECX 21:17 mawau The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode
7 0 ECX 22 rdpid RDPID and IA32_TSC_AUX
7 0 ECX 30 sgx_lc SGX Launch Configuration
9 0 ECX 31:0 dca_cap The value of IA32_PLATFORM_DCA_CAP
0xA 0 EAX 7:0 pmu_ver Performance Monitoring Unit version
0xA 0 EAX 15:8 pmu_gp_cnt_num Numer of general-purose PMU counters per logical CPU
0xA 0 EAX 23:16 pmu_cnt_bits Bit wideth of PMU counter
0xA 0 EAX 31:24 pmu_ebx_bits Length of EBX bit vector to enumerate PMU events
0xA 0 EBX 0 pmu_no_core_cycle_evt Core cycle event not available
0xA 0 EBX 1 pmu_no_instr_ret_evt Instruction retired event not available
0xA 0 EBX 2 pmu_no_ref_cycle_evt Reference cycles event not available
0xA 0 EBX 3 pmu_no_llc_ref_evt Last-level cache reference event not available
0xA 0 EBX 4 pmu_no_llc_mis_evt Last-level cache misses event not available
0xA 0 EBX 5 pmu_no_br_instr_ret_evt Branch instruction retired event not available
0xA 0 EBX 6 pmu_no_br_mispredict_evt Branch mispredict retired event not available
0xA 0 ECX 4:0 pmu_fixed_cnt_num Performance Monitoring Unit version
0xA 0 ECX 12:5 pmu_fixed_cnt_bits Numer of PMU counters per logical CPU
0xB 0 EAX 4:0 id_shift Number of bits to shift right on x2APIC ID to get a unique topology ID of the next level type
0xB 0 EBX 15:0 cpu_nr Number of logical processors at this level type
0xB 0 ECX 15:8 lvl_type 0-Invalid 1-SMT 2-Core
0xB 0 EDX 31:0 x2apic_id x2APIC ID the current logical processor
0xD 0 EAX 0 x87 X87 state
0xD 0 EAX 1 sse SSE state
0xD 0 EAX 2 avx AVX state
0xD 0 EAX 4:3 mpx MPX state
0xD 0 EAX 7:5 avx512 AVX-512 state
0xD 0 EAX 9 pkru PKRU state
0xD 0 EBX 31:0 max_sz_xcr0 Maximum size (bytes) required by enabled features in XCR0
0xD 0 ECX 31:0 max_sz_xsave Maximum size (bytes) of the XSAVE/XRSTOR save area
0xD 1 EAX 0 xsaveopt XSAVEOPT available
0xD 1 EAX 1 xsavec XSAVEC and compacted form supported
0xD 1 EAX 2 xgetbv XGETBV supported
0xD 1 EAX 3 xsaves XSAVES/XRSTORS and IA32_XSS supported
0xD 1 EBX 31:0 max_sz_xcr0 Maximum size (bytes) required by enabled features in XCR0
0xD 1 ECX 8 pt PT state
0xD 1 ECX 11 cet_usr CET user state
0xD 1 ECX 12 cet_supv CET supervisor state
0xD 1 ECX 13 hdc HDC state
0xD 1 ECX 16 hwp HWP state
0xF 0 EBX 31:0 rmid_range Maximum range (zero-based) of RMID within this physical processor of all types
0xF 0 EDX 1 l3c_rdt_mon L3 Cache RDT Monitoring supported
0xF 1 ECX 31:0 rmid_range Maximum range (zero-based) of RMID of this types
0xF 1 EDX 0 l3c_ocp_mon L3 Cache occupancy Monitoring supported
0xF 1 EDX 1 l3c_tbw_mon L3 Cache Total Bandwidth Monitoring supported
0xF 1 EDX 2 l3c_lbw_mon L3 Cache Local Bandwidth Monitoring supported
0x10 0 EBX 1 l3c_rdt_alloc L3 Cache Allocation supported
0x10 0 EBX 2 l2c_rdt_alloc L2 Cache Allocation supported
0x10 0 EBX 3 mem_bw_alloc Memory Bandwidth Allocation supported
0x12 0 EAX 0 sgx1 L3 Cache Allocation supported
0x12 1 EAX 0 sgx2 L3 Cache Allocation supported
0x15 0 EAX 31:0 tsc_denominator The denominator of the TSC/”core crystal clock” ratio
0x15 0 EBX 31:0 tsc_numerator The numerator of the TSC/”core crystal clock” ratio
0x15 0 ECX 31:0 nom_freq Nominal frequency of the core crystal clock in Hz
0x16 0 EAX 15:0 cpu_base_freq Processor Base Frequency in MHz
0x16 0 EBX 15:0 cpu_max_freq Maximum Frequency in MHz
0x16 0 ECX 15:0 bus_freq Bus (Reference) Frequency in MHz
0x17 0 EAX 31:0 max_socid Maximum input value of supported sub-leaf
0x17 0 EBX 15:0 soc_vid SOC Vendor ID
0x17 0 EBX 16 std_vid SOC Vendor ID is assigned via an industry standard scheme
0x17 0 ECX 31:0 soc_pid SOC Project ID assigned by vendor
0x17 0 EDX 31:0 soc_sid SOC Stepping ID
0x1A 0 EAX 31:24 core_type 20H-Intel_Atom 40H-Intel_Core
0x80000001 0 EAX 27:20 extfamily Extended family
0x80000001 0 EAX 19:16 extmodel Extended model
0x80000001 0 EAX 11:8 basefamily Description of Family
0x80000001 0 EAX 11:8 basemodel Model numbers vary with product
0x80000001 0 EAX 3:0 stepping Processor stepping (revision) for a specific model
0x80000001 0 EBX 31:28 pkgtype Specifies the package type
0x80000001 0 ECX 0 lahf_lm LAHF/SAHF available in 64-bit mode
0x80000001 0 ECX 1 cmplegacy Core multi-processing legacy mode
0x80000001 0 ECX 2 svm Indicates support for: VMRUN VMLOAD VMSAVE CLGI VMMCALL and INVLPGA
0x80000001 0 ECX 3 extapicspace Extended APIC register space
0x80000001 0 ECX 4 altmovecr8 Indicates support for LOCK MOV CR0 means MOV CR8
0x80000001 0 ECX 5 lzcnt LZCNT
0x80000001 0 ECX 6 sse4a EXTRQ INSERTQ MOVNTSS and MOVNTSD instruction support
0x80000001 0 ECX 7 misalignsse Misaligned SSE Mode
0x80000001 0 ECX 8 prefetchw PREFETCHW
0x80000001 0 ECX 9 osvw OS Visible Work-around support
0x80000001 0 ECX 10 ibs Instruction Based Sampling
0x80000001 0 ECX 11 xop Extended operation support
0x80000001 0 ECX 12 skinit SKINIT and STGI support
0x80000001 0 ECX 13 wdt Watchdog timer support
0x80000001 0 ECX 15 lwp Lightweight profiling support
0x80000001 0 ECX 16 fma4 Four-operand FMA instruction support
0x80000001 0 ECX 17 tce Translation cache extension
0x80000001 0 ECX 22 TopologyExtensions Indicates support for Core::X86::Cpuid::CachePropEax0 and Core::X86::Cpuid::ExtApicId
0x80000001 0 ECX 23 perfctrextcore Indicates support for Core::X86::Msr::PERF_CTL0 - 5 and Core::X86::Msr::PERF_CTR
0x80000001 0 ECX 24 perfctrextdf Indicates support for Core::X86::Msr::DF_PERF_CTL and Core::X86::Msr::DF_PERF_CTR
0x80000001 0 ECX 26 databreakpointextension Indicates data breakpoint support for Core::X86::Msr::DR0_ADDR_MASK Core::X86::Msr::DR1_ADDR_MASK Core::X86::Msr::DR2_ADDR_MASK and Core::X86::Msr::DR3_ADDR_MASK
0x80000001 0 ECX 27 perftsc Performance time-stamp counter supported
0x80000001 0 ECX 28 perfctrextllc Indicates support for L3 performance counter extensions
0x80000001 0 ECX 29 mwaitextended MWAITX and MONITORX capability is supported
0x80000001 0 ECX 30 admskextn Indicates support for address mask extension (to 32 bits and to all 4 DRs) for instruction breakpoints
0x80000001 0 EDX 0 fpu x87 floating point unit on-chip
0x80000001 0 EDX 1 vme Virtual-mode enhancements
0x80000001 0 EDX 2 de Debugging extensions IO breakpoints CR4.DE
0x80000001 0 EDX 3 pse Page-size extensions (4 MB pages)
0x80000001 0 EDX 4 tsc Time stamp counter RDTSC/RDTSCP instructions CR4.TSD
0x80000001 0 EDX 5 msr Model-specific registers (MSRs) with RDMSR and WRMSR instructions
0x80000001 0 EDX 6 pae Physical-address extensions (PAE)
0x80000001 0 EDX 7 mce Machine Check Exception CR4.MCE
0x80000001 0 EDX 8 cmpxchg8b CMPXCHG8B instruction
0x80000001 0 EDX 9 apic advanced programmable interrupt controller (APIC) exists and is enabled
0x80000001 0 EDX 11 sysret SYSCALL/SYSRET supported
0x80000001 0 EDX 12 mtrr Memory-type range registers
0x80000001 0 EDX 13 pge Page global extension CR4.PGE
0x80000001 0 EDX 14 mca Machine check architecture MCG_CAP
0x80000001 0 EDX 15 cmov Conditional move instructions CMOV FCOMI FCMOV
0x80000001 0 EDX 16 pat Page attribute table
0x80000001 0 EDX 17 pse36 Page-size extensions
0x80000001 0 EDX 20 exec_dis Execute Disable Bit available
0x80000001 0 EDX 22 mmxext AMD extensions to MMX instructions
0x80000001 0 EDX 23 mmx MMX instructions
0x80000001 0 EDX 24 fxsr FXSAVE and FXRSTOR instructions
0x80000001 0 EDX 25 ffxsr FXSAVE and FXRSTOR instruction optimizations
0x80000001 0 EDX 26 1gb_page 1GB page supported
0x80000001 0 EDX 27 rdtscp RDTSCP and IA32_TSC_AUX are available
0x80000001 0 EDX 29 lm 64b Architecture supported
0x80000001 0 EDX 30 threednowext AMD extensions to 3DNow! instructions
0x80000001 0 EDX 31 threednow 3DNow! instructions
0x80000006 0 ECX 7:0 clsize Cache Line size in bytes
0x80000006 0 ECX 15:12 l2c_assoc L2 Associativity
0x80000006 0 ECX 31:16 csize Cache size in 1K units
0x80000007 0 EDX 8 nonstop_tsc Invariant TSC available
0x80000008 0 EAX 7:0 phy_adr_bits Physical Address Bits
0x80000008 0 EAX 15:8 lnr_adr_bits Linear Address Bits
0x80000007 0 EBX 9 wbnoinvd WBNOINVD
0x8000001E 0 EAX 31:0 extended_apic_id Extended APIC ID
0x8000001E 0 EBX 7:0 core_id Identifies the logical core ID
0x8000001E 0 EBX 15:8 threads_per_core The number of threads per core is threads_per_core + 1
0x8000001E 0 ECX 7:0 node_id Node ID
0x8000001E 0 ECX 10:8 nodes_per_processor Nodes per processor { 0: 1 node else reserved }
0x8000001F 0 EAX 0 sme Secure Memory Encryption
0x8000001F 0 EAX 1 sev Secure Encrypted Virtualization
0x8000001F 0 EAX 2 vmpgflush VM Page Flush MSR
0x8000001F 0 EAX 3 seves SEV Encrypted State
0x8000001F 0 EBX 5:0 c-bit Page table bit number used to enable memory encryption
0x8000001F 0 EBX 11:6 mem_encrypt_physaddr_width Reduction of physical address space in bits with SME enabled
0x8000001F 0 ECX 31:0 num_encrypted_guests Maximum ASID value that may be used for an SEV-enabled guest
0x8000001F 0 EDX 31:0 minimum_sev_asid Minimum ASID value that must be used for an SEV-enabled SEV-ES-disabled guest

About the columns

LEAF
the value to set register eax prior to executing the cpuid

instruction.

SUBLEAF
the value to set register ecx prior to executing the cpuid instruction. It appears the cpuid instruction looks in ecx only in certain cases. Read the vendor documentation for further explaination.
register_name
the register containing the bits after cpuid execution
bits
which range or single bit position to extract from register_name
short_name
short symbolic name. Roughly correlates with /proc/cpuinfo
long_description
a few words describing the CPUID entry

How did I generate this table?

All in Emacs.

  1. Visit cpuid.csv then copy it. C-x h (mark-whole-buffer), M-w (kill-ring-save).
  2. Visit your target org-mode file.
  3. Paste C-y (yank), Uncomment the commented “key” line that has the column names in it, then move your cursor to the beginning of the first pasted line.
  4. then mark the entire pasted text. C-space (set-mark-command) followed by C-x C-x (exchange-point-and-mark) might work.
  5. Delete unwanted lines M-x flush-lines RET ^#\|^$ RET .
  6. Convert the CSV to an org-mode table C-u C-c | (org-table-create-or-convert-from-region)
  7. That’s it.

Other tables on the net

There are other CPUID tables online, but they didn’t quite meet my needs of compactness.

  • The Wikipedia CPUID article offers a detailed breakdown of all the features
  • The Intel datasheet, AMD datasheet, and additional resources hyperlinked in the aforementioned Wikipedia CPUID article’s References, Further reading, and External links sections.
  • Bunch of others discoverable via Google that are quite detailed.

A few ways to display CPUID feature flags

/proc/cpuinfo

In the following example see the flags field. This approach requires no external tooling, only a booted Linux kernel. The cinch is one has to correlate the short-names with descriptions or have a brilliant memory.

$ cat /proc/cpuinfo
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 9
model name	: Intel(R) Pentium(R) M processor 1600MHz
stepping	: 5
microcode	: 0x7
cpu MHz		: 1600.000
cache size	: 1024 KB
physical id	: 0
siblings	: 1
core id		: 0
cpu cores	: 1
apicid		: 0
initial apicid	: 0
fdiv_bug	: no
f00f_bug	: no
coma_bug	: no
fpu		: yes
fpu_exception	: yes
cpuid level	: 2
wp		: yes
flags		: fpu vme de pse tsc msr mce cx8 sep mtrr pge mca cmov clflush dts acpi mmx fxsr sse sse2 tm pbe bts cpuid est tm2
bugs		: cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit mmio_unknown
bogomips	: 3198.33
clflush size	: 64
cache_alignment	: 64
address sizes	: 32 bits physical, 32 bits virtual
power management:

lscpu

lscpu seems to provide the same information as the above, but with a slimmer output. util-linux provides this package on most distros, so it’s oft installed out of the box.

$ lscpu
Architecture:                       i686
CPU op-mode(s):                     32-bit
Address sizes:                      32 bits physical, 32 bits virtual
Byte Order:                         Little Endian
CPU(s):                             1
On-line CPU(s) list:                0
Vendor ID:                          GenuineIntel
Model name:                         Intel(R) Pentium(R) M processor 1600MHz
CPU family:                         6
Model:                              9
Thread(s) per core:                 1
Core(s) per socket:                 1
Socket(s):                          1
Stepping:                           5
CPU(s) scaling MHz:                 100%
CPU max MHz:                        1600.0000
CPU min MHz:                        600.0000
BogoMIPS:                           3198.33
Flags:                              fpu vme de pse tsc msr mce cx8 sep mtrr pge mca cmov clflush dts acpi mmx fxsr sse sse2 tm pbe bts cpuid est tm2
Vulnerability Gather data sampling: Not affected
Vulnerability Itlb multihit:        KVM: Mitigation: VMX unsupported
Vulnerability L1tf:                 Vulnerable
Vulnerability Mds:                  Vulnerable: Clear CPU buffers attempted, no microcode; SMT disabled
Vulnerability Meltdown:             Vulnerable
Vulnerability Mmio stale data:      Unknown: No mitigations
Vulnerability Retbleed:             Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass:    Vulnerable
Vulnerability Spectre v1:           Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:           Mitigation; Retpolines, STIBP disabled, RSB filling, PBRSB-eIBRS Not affected
Vulnerability Srbds:                Not affected
Vulnerability Tsx async abort:      Not affected

cpuid

cpuid provides a verbose output with descriptions of all CPUID feature flags. Great if one can install an additional software package available on most distros.

$ cpuid
CPU 0:
   vendor_id = "GenuineIntel"
   version information (1/eax):
      processor type  = primary processor (0)
      family          = 0x6 (6)
      model           = 0x9 (9)
      stepping id     = 0x5 (5)
      extended family = 0x0 (0)
      extended model  = 0x0 (0)
      (family synth)  = 0x6 (6)
      (model synth)   = 0x9 (9)
   miscellaneous (1/ebx):
      process local APIC physical ID = 0x0 (0)
      maximum IDs for CPUs in pkg    = 0x0 (0)
      CLFLUSH line size              = 0x8 (8)
      brand index                    = 0x16 (22)
   brand id = 0x16 (22): Intel Pentium M, .13um
   feature information (1/edx):
      x87 FPU on chip                        = true
      VME: virtual-8086 mode enhancement     = true
      DE: debugging extensions               = true
      PSE: page size extensions              = true
      TSC: time stamp counter                = true
      RDMSR and WRMSR support                = true
      PAE: physical address extensions       = false
      MCE: machine check exception           = true
      CMPXCHG8B inst.                        = true
      APIC on chip                           = false
      SYSENTER and SYSEXIT                   = true
      MTRR: memory type range registers      = true
      PTE global bit                         = true
      MCA: machine check architecture        = true
      CMOV: conditional move/compare instr   = true
      PAT: page attribute table              = true
      PSE-36: page size extension            = false
      PSN: processor serial number           = false
      CLFLUSH instruction                    = true
      DS: debug store                        = true
      ACPI: thermal monitor and clock ctrl   = true
      MMX Technology                         = true
      FXSAVE/FXRSTOR                         = true
      SSE extensions                         = true
      SSE2 extensions                        = true
      SS: self snoop                         = false
      hyper-threading / multi-core supported = false
      TM: therm. monitor                     = true
      IA64                                   = false
      PBE: pending break event               = true
   feature information (1/ecx):
      PNI/SSE3: Prescott New Instructions     = false
      PCLMULDQ instruction                    = false
      DTES64: 64-bit debug store              = false
      MONITOR/MWAIT                           = false
      CPL-qualified debug store               = false
      VMX: virtual machine extensions         = false
      SMX: safer mode extensions              = false
      Enhanced Intel SpeedStep Technology     = true
      TM2: thermal monitor 2                  = true
      SSSE3 extensions                        = false
      context ID: adaptive or shared L1 data  = false
      SDBG: IA32_DEBUG_INTERFACE              = false
      FMA instruction                         = false
      CMPXCHG16B instruction                  = false
      xTPR disable                            = false
      PDCM: perfmon and debug                 = false
      PCID: process context identifiers       = false
      DCA: direct cache access                = false
      SSE4.1 extensions                       = false
      SSE4.2 extensions                       = false
      x2APIC: extended xAPIC support          = false
      MOVBE instruction                       = false
      POPCNT instruction                      = false
      time stamp counter deadline             = false
      AES instruction                         = false
      XSAVE/XSTOR states                      = false
      OS-enabled XSAVE/XSTOR                  = false
      AVX: advanced vector extensions         = false
      F16C half-precision convert instruction = false
      RDRAND instruction                      = false
      hypervisor guest status                 = false
   cache and TLB information (2):
      0xb0: instruction TLB: 4K, 4-way, 128 entries
      0xb3: data TLB: 4K pages, 4-way, 128 entries
      0x02: instruction TLB: 4M pages, 4-way, 2 entries
      0x87: L2 cache: 1M, 8-way, 64 byte lines
      0x30: L1 cache: 32K, 8-way, 64 byte lines
      0x04: data TLB: 4M pages, 4-way, 8 entries
      0x2c: L1 data cache: 32K, 8-way, 64 byte lines
   extended feature flags (0x80000001/edx):
      SYSCALL and SYSRET instructions        = false
      execution disable                      = false
      1-GB large page support                = false
      RDTSCP                                 = false
      64-bit extensions technology available = false
   Intel feature flags (0x80000001/ecx):
      LAHF/SAHF supported in 64-bit mode     = false
      LZCNT advanced bit manipulation        = false
      3DNow! PREFETCH/PREFETCHW instructions = false
   brand = "        Intel(R) Pentium(R) M processor 1600MHz"
   (instruction supported synth):
      MWAIT = false
   (multi-processing synth) = none
   (multi-processing method) = Intel leaf 1
   (uarch synth) = Intel {P6 Pentium M}, .13um
   (synth) = Intel Pentium M (Banias B1) {P6 Pentium M}, .13um

kcpuid (in kernel tree)

kcpuid is a small utility shipped with the Linux kernel tree in directory tools/arch/x86/kcpuid (gitweb). It appears installable with make install, though one can run it in-place:

$ cd tools/arch/x86/kcpuid
$ make
cc -Wextra -O2 -Wall -I../../../include -o kcpuid kcpuid.c
$./kcpuid -d
CPU features:
=============

CPUID_0x0_ECX[0x0]:
         EBX: 0x756e6547
         ECX: 0x6c65746e
         EDX: 0x49656e69

CPUID_0x1_ECX[0x0]:
         eist                - Enhanced Intel SpeedStep Technology
         tm2                 - Thermal Monitor 2
         fpu                 - x87 FPU on chip
         vme                 - Virtual-8086 Mode Enhancement
         de                  - Debugging Extensions
         pse                 - Page Size Extensions
         tsc                 - Time Stamp Counter
         msr                 - RDMSR and WRMSR Support
         mce                 - Machine Check Exception
         cx8                 - CMPXCHG8B instr
         sep                 - SYSENTER and SYSEXIT instrs
         mtrr                - Memory Type Range Registers
         pge                 - Page Global Bit
         mca                 - Machine Check Architecture
         cmov                - Conditional Move Instrs
         pat                 - Page Attribute Table
         clflush             - CLFLUSH instr
         ds                  - Debug Store
         acpi                - Thermal Monitor and Software Controlled Clock Facilities
         mmx                 - Intel MMX Technology
         fxsr                - XSAVE and FXRSTOR Instrs
         sse                 - SSE
         sse2                - SSE2
         tm                  - Thermal Monitor
         pbe                 - Pending Break Enable

CPUID_0x2_ECX[0x0]:
         EAX: 0x02b3b001
         EBX: 0x00000000
         ECX: 0x00000000
         EDX: 0x2c043087

CPUID_0x80000000_ECX[0x0]:
         EAX: 0x80000004
         EBX: 0x00000000
         ECX: 0x00000000
         EDX: 0x00000000

CPUID_0x80000002_ECX[0x0]:
         EAX: 0x20202020
         EBX: 0x20202020
         ECX: 0x65746e49
         EDX: 0x2952286c

CPUID_0x80000003_ECX[0x0]:
         EAX: 0x6e655020
         EBX: 0x6d756974
         ECX: 0x20295228
         EDX: 0x7270204d

CPUID_0x80000004_ECX[0x0]:
         EAX: 0x7365636f
         EBX: 0x20726f73
         ECX: 0x30303631
         EDX: 0x007a484d

Conclusion

CPUID is an interesting x86 instruction for it does nothing, but tell a tale of what the gear can do, if given the right software. Published on a 20 year old computer using a modern publishing workflow, thanks to the right software and CPUID detected CPU features.

What’s worse than a fire on a boat? A fire aboard an air balloon. Rip my fly.io app.

Affected Apps:

  • sillypaste-db

A server hosting some of your apps has suffered irreparable hardware damage. Please migrate your Fly Machines to other hosts and restore volumes from any backups.

All good things come to an end, including this pastebin project. If I find myself using it again, I may spin up a fresh database if that opportunity presents itself.

I wouldn’t recommend fly.io at this time. Having been erroneously billed (then quickly refunded) a couple times, fought with their V1 stack and data corruption issues, and it goes on. At one time I ended up with the PostgresSQL database container crashing with Out of Memory… despite issuing countless scale commands. Eventually I paid for the $20/mo email support for the support staff to tell me flatly - you must migrate and yes v1 is still considered robust for some workloads. I’m pretty sure the reliability claim is a white lie, but indeed, I had to upgrade. Turned out to be tricky due to inconsistent documentation on V1 vs V2 features. Had to ask another question.

It should be noted that support was quick to reply to my email because I paid for the $20 email support plan; support on the community forums is best effort and will not lead to a fruitful support conversation.

What went well with Fly.io?

Now that fly.io’s critical negative review has been written, let’s review some of Fly.io’s wins.

  • flyctl command line tool compares favorable against heroku. Simpler operation, less features to confound over.
  • Its web design is modern and nice… but like many UIs designed for touch input, it suffers from low density… which pushed me to use the CLI wherever possible.
  • Support forum uses Discourse, a wonderful no-nonsense support forum experience.
  • When it works, it works really well.
  • It was a cheap experiment. You do get what you pay for (free hosting = it can burn down at any time and that’s ok).

Alternatives for hosting Sillypaste

I have no first-hand endorsements, but next I’d assess AWS Lambda, Digital Ocean Apps, or a simple VPS for hosting this modest Django webapp. A service that gets billing right, maintains consistent documentation, and has a working reliable PaaS offering is ideal.

For now, Sillypaste shall remain offline but the code is always available on GitHub. All I need to do to remove the DNS paste.winny.tech entry is delete it from my terraform project then run terraform apply.