How to Run Linux Before First Silicon
In a modern SoC project, first silicon bring-up is one of the most compressed and consequential phases of the development cycle. A new chip arrives from fabrication, and the team must make power, clocks, resets, JTAG, boot modes, DDR, flash, SerDes, PCIe, Ethernet, Linux, device drivers, and board-level diagnostics work together under real schedule pressure.
Linux bring-up is often described as a software activity that begins after the chip returns. That view is increasingly incomplete. Linux does not run in isolation. It exercises the CPU reset path, memory map, interrupt controller, timer, MMU, cache hierarchy, DDR initialization, DMA behavior, clock and reset controls, device registers, firmware handoff, and device tree description. When Linux boots, it is not merely starting an operating system; it is probing the system-level contract between hardware and software.
This is why running Linux before first silicon has become a serious engineering practice. It is not about pretending that a model is the same as real silicon. It is about moving a large class of software-visible integration risks into a controlled, repeatable, and observable environment before the physical chip is available.
The objective is modest but important: by the time first silicon arrives, the team should have a validated baseline for the boot flow, device tree, key kernel startup phases, critical driver paths, and major issues in address maps, interrupts, DMA, memory attributes, and firmware handoff.
What It Means to Run Linux Before Silicon
Strictly speaking, there is no real chip before first silicon. Running Linux before silicon therefore means executing the Linux boot path and selected software workloads on a pre-silicon platform that represents the SoC with sufficient fidelity for the question being asked.
That platform may be RTL simulation, hardware emulation, an FPGA prototype, a virtual platform, QEMU, a SystemC/TLM model, or a hybrid environment that combines several of these technologies. Each platform has a different balance of speed, fidelity, and observability. The common purpose is to allow software to become an early consumer of the chip design.
Three levels of validation should be separated.
The first level is functional correctness. Can Linux see the expected memory map? Can it initialize the UART, timer, interrupt controller, and early console? Can the kernel decompress, enable the MMU, enumerate devices, and probe essential drivers?
The second level is interface consistency. Do the device tree, register specification, RTL integration, firmware configuration, bootloader settings, and driver code all describe the same hardware? Many bring-up failures are not caused by sophisticated logic bugs. They come from a wrong base address, an interrupt ID mismatch, an incorrect clock name, an inverted reset polarity, or an outdated reserved-memory region.
The third level is timing and performance realism. Pre-silicon platforms can expose many system problems, but they do not all represent final timing, bandwidth, latency, power, or analog behavior. The proper goal of pre-silicon Linux bring-up is to validate software-visible system behavior early, not to replace post-silicon validation.
The Linux Bring-up Chain
Linux bring-up does not begin at the first line of kernel C code. In a typical SoC, the path includes reset release, BootROM, first-stage boot code, DDR initialization, firmware, secure monitor code, U-Boot or another bootloader, the Linux kernel, the device tree, and the root filesystem.
In many Arm-based SoCs, the chain may include BootROM, SPL or FSBL, TF-A, U-Boot, and the Linux kernel. Naming differs across projects, but the structure is similar. Each stage depends on the hardware state established by the previous stage, and each stage prepares the environment for the next.
BootROM usually performs the earliest actions after reset: selecting boot media, setting up a minimal execution environment, and loading the next image. SPL or FSBL often initializes DDR, configures essential clocks and resets, and prepares basic peripherals. TF-A or a similar firmware layer handles exception levels, security state transitions, power management interfaces, and runtime services. U-Boot loads the kernel, passes the device tree, and prepares boot arguments. The Linux kernel then initializes the MMU, scheduler, interrupt subsystem, timer framework, memory management, driver model, and user space.
From a bring-up perspective, Linux can boot only if several hardware-software conditions are simultaneously true:
- The CPU reset vector and exception vectors are correct.
- Boot mode, image format, and load addresses match.
- SRAM or DDR is available at the stage that uses it.
- The timer and interrupt controller match kernel expectations.
- The device tree accurately describes hardware resources.
- Clock, reset, and power-domain dependencies are handled correctly.
- A UART or equivalent logging path is available early enough.
- Cache, MMU, DMA, and memory attributes are consistent.
These conditions cut across architecture, RTL, verification, firmware, software, board design, and system integration. Linux bring-up is therefore a strong indicator of SoC system maturity.
Why Waiting for First Silicon Is Risky
During first silicon bring-up, time and diagnosability are scarce. The team is dealing with a new physical device. A failure may come from RTL, backend constraints, packaging, PCB design, power sequencing, clocking, reset logic, DDR training, boot flash, JTAG configuration, test scripts, or software. If the Linux boot path also starts from zero at that moment, the search space becomes too large.
Consider a simple symptom: no serial output. The root cause may be that the CPU is not fetching from the expected address, BootROM did not load the image, DDR initialization failed, the UART clock is disabled, pinmux is wrong, reset remains asserted, an exception path loops silently, or early logs are placed in inaccessible memory. Without a pre-silicon baseline, it is difficult to separate a silicon or board problem from a software integration problem.
Another common case is a kernel that prints some logs but stops during driver probing, DMA initialization, or root filesystem mounting. The issue may be in the device tree, register semantics, interrupt clear sequence, cache coherency, DMA address width, IOMMU configuration, or reserved-memory layout. Many of these problems are not obvious in block-level RTL tests, but they appear quickly once Linux becomes the system workload.
The value of running Linux early is that part of this uncertainty can be moved from the first-silicon lab into a repeatable engineering platform. First silicon work can then focus more clearly on real silicon behavior, board issues, PVT conditions, performance, power, and long-term reliability instead of rediscovering basic software-visible interface problems.
Pre-silicon Platforms and Their Roles
Different pre-silicon platforms answer different questions. A mature flow usually combines them rather than relying on a single environment.
RTL simulation offers high fidelity and strong observability. It can expose internal signals, waveforms, state machines, and bus transactions. It is useful for early BootROM behavior, register access, exception paths, and local driver issues. Its limitation is speed. Running a full Linux system in pure RTL simulation is often impractical. Simulation is best suited for short, precise, high-visibility debug tasks.
Hardware emulation can handle larger RTL systems at much higher speed than simulation while preserving useful debug capability. It is well suited for SoC integration, boot chain validation, early kernel startup, interrupt behavior, DMA flows, and multi-IP interaction. Its value is the combination of RTL fidelity and software execution speed, although infrastructure and resource costs are significant.
FPGA prototyping provides speed and real IO connectivity. It can support longer Linux runs, real peripherals, driver stress tests, networking, storage, PCIe, camera pipelines, display paths, or AI inference workloads. It is particularly useful for creating a hardware-like software validation environment before first silicon. The trade-off is that FPGA implementations may differ from the final ASIC in clocking, memory structures, substituted IP, timing behavior, and internal observability.
Virtual platforms are usually based on instruction set simulation, SystemC/TLM, or architectural models. They can enable software work before complete RTL is available. They are useful for bootloader development, firmware, kernel configuration, driver framework work, and early device tree development. Their limitation is model accuracy. A passing test on a virtual platform is meaningful only to the extent that the model represents the relevant hardware behavior.
QEMU is often used for early software bring-up, especially for CPU, kernel, root filesystem, and common peripheral paths. It is fast, convenient for automation, and friendly to continuous integration. For project-specific IP, however, its usefulness depends on the quality of custom models. Complex accelerators, private DMA behavior, and nonstandard bus semantics often require additional modeling or integration with other platforms.
Hybrid validation combines methods. For example, the CPU and most software may run in a virtual platform while selected RTL blocks run in emulation or FPGA. Or Linux may run on an FPGA prototype while short, focused failures are reproduced in simulation for waveform-level analysis. The purpose of a hybrid approach is not elegance; it is a practical balance among speed, fidelity, observability, and cost.
From Booting to Validating
Running Linux before first silicon should not stop at seeing a few lines of boot log. The work becomes useful when bring-up goals are layered and each layer has a clear validation target.
The first layer is minimal visibility. The system moves from reset into the first software stage, prints early logs, accesses basic registers, and confirms that CPU execution, SRAM, UART, JTAG, or semihosting is alive. This layer answers the most basic question: is the system executing in a diagnosable way?
The second layer is boot-chain continuity. BootROM, SPL or FSBL, firmware, U-Boot, and the kernel image must agree on load addresses, image formats, exception levels, memory layout, and boot arguments. This stage often exposes address conflicts, incorrect image placement, security-state mismatches, and DDR initialization dependencies.
The third layer is early kernel startup. Linux enables the MMU, builds page tables, initializes the timer, interrupt controller, scheduler, and basic memory management. Failures here often involve memory attributes, timer frequency, interrupt-controller description, exception-level assumptions, or missing device tree nodes.
The fourth layer is device model and driver probing. The kernel discovers devices through the device tree or ACPI and drivers initialize hardware based on properties such as compatible strings, register regions, interrupts, clocks, resets, DMA ranges, and reserved memory. This is where hardware-software interface consistency is tested intensively.
The fifth layer is data-path validation. Once DMA, cache coherency, IOMMU, PCIe, Ethernet, storage, display, camera, NPU, or other accelerators enter the path, Linux is no longer just booting. It is driving real data movement. Hidden issues appear in descriptor rings, buffer ownership, interrupt completion, memory barriers, and error recovery.
The sixth layer is long-running and representative workloads. The system mounts a root filesystem, enters user space, runs diagnostics, handles reboot, recovers from errors, and remains observable under typical load. For an AI SoC, this may include model loading, input preprocessing, NPU inference, CPU post-processing, and output handling. This layer begins to resemble the system behavior that matters after first silicon.
This layering prevents a common mistake: treating a partial boot log as a completed bring-up. Booting Linux is a milestone, but stable use of hardware resources is where system validation becomes meaningful.
Device Tree as a Critical Contract
In embedded Linux systems, the device tree is often underestimated. It may look like configuration data, but it is actually a structured expression of hardware facts. Linux does not read RTL or hardware specifications. It sees base addresses, interrupts, clocks, resets, memory regions, DMA relationships, bus topology, and device compatibility through the device tree.
If the device tree does not match the current RTL integration, kernel behavior diverges from hardware reality. A wrong base address causes access to the wrong region. A wrong interrupt ID makes a driver wait for an interrupt that never arrives. A wrong clock frequency affects UART baud rate, timer ticks, or driver timeouts. An incorrect reserved-memory region can allow the kernel allocator to overwrite firmware memory, DMA buffers, or secure regions.
For this reason, a large part of pre-silicon Linux bring-up is about keeping the device tree, register specification, RTL address map, verification environment, and bootloader configuration consistent. This is not clerical work. It is part of the software-visible architecture of the SoC.
More mature flows manage the memory map, interrupt map, clock and reset relationships, and register schema in structured forms, then generate or check device trees, header files, UVM register models, firmware configuration, and documentation. This reduces errors caused by manual copying across teams and tools.
Common Failure Modes
Running Linux before first silicon tends to expose practical integration problems.
Address-map errors are common. An IP base address may change after RTL integration while the device tree or driver still uses an older value. Address windows may overlap. Secure and non-secure attributes may be inconsistent. The DMA-visible address space may differ from the CPU-visible address space. These failures can appear as bus errors, timeouts, silent hangs, or unexplained data corruption.
Interrupt issues are equally common. An interrupt ID may be wired incorrectly. Polarity may be wrong. Level and edge semantics may not match software assumptions. The interrupt-clear sequence may be opposite to what the driver expects. Linux drivers often use interrupts to complete asynchronous work, so unclear interrupt semantics can produce hangs, repeated interrupts, or intermittent packet loss.
Clock and reset issues can make drivers look nondeterministic. A block may require a stabilization delay after clock enable. Reset release may depend on a parent domain. Some registers may be accessible only after a power domain is enabled. If these constraints are not represented in software-visible interfaces, Linux initialization will eventually encounter hidden dependencies.
DMA and cache coherency issues are especially important in AI SoCs, high-speed IO, and multicore systems. DMA may not see descriptors written by the CPU. The CPU may read stale cache lines after DMA writes data back. Buffers may violate alignment requirements. Cache maintenance may be missing or ordered incorrectly. IOMMU mappings may not match hardware transaction attributes. These failures are often intermittent, which makes early reproduction on controlled platforms valuable.
Boot-flow issues often occur at software stage boundaries. One stage may overwrite memory used by another. The kernel decompression address may conflict with a firmware-reserved region. TF-A may pass boot parameters that do not match U-Boot assumptions. Exception level or security-state transitions may not match kernel configuration. These are system-level problems rather than isolated block bugs, but they can completely block boot.
Special Considerations for AI SoCs
For an AI SoC, Linux bring-up is not only about starting the kernel. It also needs to bring the NPU, DPU, DSP, ISP, video codec, DMA engines, memory controller, and runtime software into a coherent data path.
A typical edge AI pipeline may receive data from a sensor or camera, process it through an ISP or preprocessing block, write it into DDR buffers, run inference on an NPU, and then let the CPU, display engine, network interface, or storage subsystem consume the result. The critical questions are not limited to whether an NPU operator is correct. The system must allocate buffers, schedule DMA, signal completion through interrupts, maintain cache coherency, manage queues in runtime software, and recover from error states.
Running Linux before first silicon allows the basic AI software stack to be validated early. The driver can probe the device. Firmware can be loaded. The runtime can open the device node. The memory allocator can provide contiguous or IOMMU-mapped buffers. A simple model can exercise an end-to-end path. Even if performance numbers are not representative of final silicon, this type of validation can reduce integration risk significantly.
For universities and research institutes, this system view is also important. An AI chip is not only a matrix multiplication engine. A usable AI SoC requires an operating system, memory subsystem, drivers, compiler support, runtime software, and application context to converge into a working system. Linux bring-up provides a concrete way to observe that hardware-software relationship.
Defining a Practical Completion Point
Pre-silicon Linux bring-up cannot cover every issue that real silicon may expose. A useful completion point should therefore be defined in terms of repeatability, diagnosability, and regression value.
First, the boot chain should be stable. The system should enter the expected boot path, load the bootloader, kernel, and device tree, and provide traceable logs, versions, load addresses, and exception states at each stage.
Second, the kernel should reach known milestones. At minimum, early console, MMU, timer, interrupt controller, memory initialization, and basic driver probing should be understood. For a fuller Linux scenario, mounting a root filesystem, entering user space, and running basic commands form an important baseline.
Third, key peripherals should have minimal validation loops. UART, timer, GPIO, I2C, SPI, Ethernet, PCIe, DMA, storage, or AI accelerators do not need to reach final performance before silicon, but they should at least demonstrate register access, interrupt response, data movement, and error-path behavior.
Fourth, failures should be reproducible and archived. Each failure should be associated with a platform version, RTL revision, device tree version, bootloader version, kernel configuration, logs, and test steps. Much of the value of pre-silicon bring-up comes from repeatability. A one-time successful boot is useful, but it is not yet an engineering baseline.
Fifth, platform differences should be explicit. Which behaviors come from real RTL? Which come from a model? Which IP blocks are substituted in the FPGA prototype? Which clock rates and bandwidth numbers do not represent final ASIC behavior? Pre-silicon conclusions are useful only when their boundaries are clear.
Limits and Engineering Boundaries
Running Linux before first silicon does not eliminate all risk. Real chips can still expose problems that pre-silicon platforms do not cover, including power integrity, clock jitter, DDR margin, SerDes behavior, analog IP characteristics, voltage and temperature corners, packaging effects, and board-level signal integrity.
Even at the digital level, FPGA prototypes may differ from ASICs. FPGA memory primitives, clock networks, substituted IP, timing constraints, and bus latencies may not match final silicon. Virtual platforms run early and fast, but the higher the abstraction, the more carefully results must be interpreted.
The correct positioning of pre-silicon Linux bring-up is therefore not that all bring-up is finished before the chip returns. A more rigorous statement is that major software-visible paths can be validated before silicon, reducing system-level risk during first-silicon bring-up.
This distinction matters. A disciplined engineering claim is not “Linux is fully validated before silicon.” It is: “With the right platforms, the Linux boot path and a meaningful set of hardware-software interfaces can be exercised before the chip returns, reducing uncertainty in the first-silicon phase.”
Closing Perspective
Running Linux before first silicon is a system engineering problem. It involves SoC architecture, boot flow, firmware, device tree, kernel configuration, drivers, memory systems, interrupts, DMA, validation platforms, and collaboration across teams.
The real value is not a single successful boot. The value is a repeatable path: boot Linux on a model or prototype, use Linux to test software-visible hardware interfaces, diagnose failures through logs and platform debug, and feed corrections back into RTL, specifications, device tree, bootloader, firmware, and drivers.
First silicon remains irreplaceable. Only real silicon can fully answer questions about final functionality, performance, power, reliability, manufacturing behavior, and physical integration. But before that point, Linux can already serve as a serious system validation workload.
In that sense, pre-silicon Linux bring-up is not a simple shift of post-silicon work to an earlier date. It is a way for an SoC project to face real system software requirements before tapeout. It moves the design beyond modules, waveforms, and specification tables into an executable engineering loop where the system can boot, run, fail, be diagnosed, and be improved before the first chip arrives.