Skip to content

kbuild: stop adding arch/x86/pci and power unconditionally - #81

Merged
fionera merged 2 commits into
hermeticbuild:mainfrom
ulfjack:kbuild-no-add-unconditionally
Aug 12, 2026
Merged

kbuild: stop adding arch/x86/pci and power unconditionally#81
fionera merged 2 commits into
hermeticbuild:mainfrom
ulfjack:kbuild-no-add-unconditionally

Conversation

@ulfjack

@ulfjack ulfjack commented Aug 10, 2026

Copy link
Copy Markdown

x86's ARCH_DRIVERS was hardcoded to "arch/x86/pci/ arch/x86/power/" in both architectures.bzl and linux_image_repository.bzl. Upstream those directories are config-gated (arch/x86/Makefile:285-291):

  drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
  drivers-$(CONFIG_PCI)            += arch/x86/pci/
  drivers-$(CONFIG_PM)             += arch/x86/power/

and Makefile:1220 exports the already-resolved result:

  export ARCH_DRIVERS := $(drivers-y) $(drivers-m)

which Kbuild:110 then appends with obj-y += $(ARCH_DRIVERS). Naming the directories directly hands the model drivers-y's value for one particular config, as a constant.

The gates are not lost, though -- the Kbuild tree parser reads arch/x86/Makefile as a root makefile and already descends into drivers-$(CONFIG_PCI) with the condition attached. So ARCH_DRIVERS was not supplying missing information, it was adding a second, ungated copy of information the parser already had. Two consequences:

  1. With CONFIG_PCI=n the arch/x86/pci objects were emitted anyway, and the build failed rather than dropping them:

    arch/x86/pci/bus_numa.c:52:3: error: call to undeclared function
    'pci_add_resource'
    

    (pci.h only declares it under CONFIG_PCI.) Same shape for CONFIG_PM=n and arch/x86/power.

  2. Even with CONFIG_PCI=y the duplicate perturbed the result. Link order became power before pci, where upstream's drivers-y order is pci then power, and arch/x86/power/cpu.o got its per-object flags twice (flags: [-fno-stack-protector, -fno-stack-protector], remove_flags: [$(CC_FLAGS_LTO), $(CC_FLAGS_LTO)]), which changes its content ID and so its cache identity.

Emptying ARCH_DRIVERS, as the arm64 descriptor already does, leaves the gated descent as the single source of truth.

Measured with the standalone generator:

  • CONFIG_PCI=y baseline: 1195 object_variants before and after, same set of objects; the arch/x86/pci block moves ahead of arch/x86/power, and arch/x86/power/cpu.o loses its duplicated flags.
  • CONFIG_PCI=n: 1118 object_variants with 9 stale arch/x86/pci objects before, 1109 with none after.
  • A workspace with CONFIG_PCI unset failed to build before and now builds @min_asn1//:vmlinux.

Worth noting how this was found: it was not on the list from the config work, it surfaced only when a full vmlinux was built from a config that happened to leave CONFIG_PCI unset. Like the ASN.1 defect, the model looked fine and the compiler disagreed.

x86's ARCH_DRIVERS was hardcoded to "arch/x86/pci/ arch/x86/power/" in
both architectures.bzl and linux_image_repository.bzl. Upstream those
directories are config-gated (arch/x86/Makefile:285-291):

```
  drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
  drivers-$(CONFIG_PCI)            += arch/x86/pci/
  drivers-$(CONFIG_PM)             += arch/x86/power/
```

and Makefile:1220 exports the already-resolved result:

```
  export ARCH_DRIVERS := $(drivers-y) $(drivers-m)
```

which Kbuild:110 then appends with obj-y += $(ARCH_DRIVERS). Naming the
directories directly hands the model drivers-y's *value* for one
particular config, as a constant.

The gates are not lost, though -- the Kbuild tree parser reads
arch/x86/Makefile as a root makefile and already descends into
drivers-$(CONFIG_PCI) with the condition attached. So ARCH_DRIVERS was
not supplying missing information, it was adding a second, ungated copy
of information the parser already had. Two consequences:

1. With CONFIG_PCI=n the arch/x86/pci objects were emitted anyway, and
   the build failed rather than dropping them:

     ```
     arch/x86/pci/bus_numa.c:52:3: error: call to undeclared function
     'pci_add_resource'
     ```

   (pci.h only declares it under CONFIG_PCI.) Same shape for
   CONFIG_PM=n and arch/x86/power.

2. Even with CONFIG_PCI=y the duplicate perturbed the result. Link order
   became power before pci, where upstream's drivers-y order is pci then
   power, and arch/x86/power/cpu.o got its per-object flags twice
   (flags: [-fno-stack-protector, -fno-stack-protector], remove_flags:
   [$(CC_FLAGS_LTO), $(CC_FLAGS_LTO)]), which changes its content ID and
   so its cache identity.

Emptying ARCH_DRIVERS, as the arm64 descriptor already does, leaves the
gated descent as the single source of truth.

Measured with the standalone generator:

  - CONFIG_PCI=y baseline: 1195 object_variants before and after, same
    set of objects; the arch/x86/pci block moves ahead of
    arch/x86/power, and arch/x86/power/cpu.o loses its duplicated flags.
  - CONFIG_PCI=n: 1118 object_variants with 9 stale arch/x86/pci
    objects before, 1109 with none after.
  - A workspace with CONFIG_PCI unset failed to build before and now
    builds @min_asn1//:vmlinux.

bazel test //internal/... stays at 116/116.

Worth noting how this was found: it was not on the list from the config
work, it surfaced only when a full vmlinux was built from a config that
happened to leave CONFIG_PCI unset. Like the ASN.1 defect, the model
looked fine and the compiler disagreed.
@ulfjack

ulfjack commented Aug 11, 2026

Copy link
Copy Markdown
Author

I think the test failure is a false positive. It's better to use aquery to count the actions, see #82.

@fionera
fionera merged commit 62e587a into hermeticbuild:main Aug 12, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants