45 Drives - HL15 - BIOS, ReBAR, Intel ARC Pro B50, TrueNAS and LLMs

I just thought that my adventures with my HL15 might interest some people here, so I’ll describe what I’ve done, where I’m at and what remains to be done.

I bought one of the pre-built OG HL15s and have been using it for a few years with TrueNAS with storage related services, MinIO for S3 and Proxmox Backup Server.

As this is an always on system, I decided to add a GPU to it so that I could experiment with local LLMs and after seeing Wendell’s review of Intel ARC Pro B50 decided to buy one.

This is where the fun began :melting_face:

The HL15 Motherboard doesn’t support ReBAR

The Supermicro X11SPH-NCTPF doesn’t support ReBAR out of the box, so I had to upgrade and patch the BIOS to enable it.

I used the ReBARUEFI Project for this.

I followed the guide by OdinVex: Guide to Patching the Supermicro Super X10/X11 Series

Backup

Before I did anything I used a CH341A USB Adapter on another PC to make a hardware level backup of the current BIOS. Getting those pins to stay on was a pain!

Get the BIOS

You can get the BIOS by registering with Supermicro and downloading the firmware.

Patching the BIOS

This was annoying, I only have one old Windows 10 machine and had to fire that up to use the required Aptio Tool (you’ll have to find that yourself).

Following the official instructions on the procedure was easy enough, easier than finding the required tool.

Updating the BIOS

I used the HL15’s IPMI to upgrade the BIOS. For basic functionality there is a way to create a key yourself (you’ll have to find that yourself).

Configuring the BIOS

This is where things started getting more difficult due to the Appliance nature of TrueNAS.

Especially things like installing a developer environment and compiling it all for the ReBarState tool, which is used to configure the ReBAR values in the BIOS.

With having to unlock the installation for such modifications and for all sorts of driver shenanigans regarding the required Xe drivers, I decided to migrate my TrueNAS box to Proxmox.

Migrating to Proxmox

This was painless too and there many guides to doing this, so here are just the basics.

  1. Backup configuration
  2. Export storage pool
  3. Install Proxmox
  4. Enable IOMMU
  5. Install TrueNAS in a VM
  6. Pass through the required PCIe devices, in my case:
    • SATA controller: Intel Corporation C620 Series Chipset Family SATA Controller [AHCI mode]
    • Serial Attached SCSI controller: Broadcom / LSI SAS3008 PCI-Express Fusion-MPT SAS-3
    • 2 x Intel Corporation NVMe Optane Memory Series
  7. Start VM
  8. Import storage pool
  9. Restore configuration

The only thing that required any real tinkering was the networking, when switching from hardware NICs to virtual ones.

Intel ARC Pro B50

Hardware installation

I used a 16x riser (4x4x8) where the lanes are split into 2 * 4x for NVMe drives (my 2 Optanes) and the B50 on top at 8x.

This threw me for a loop because when I looked at the lanes ist said I was only connected at 1x.

Battlemage is really x8

Link state on device shows LnkSta: Speed 2.5GT/s, Width x1 but it should be x8. This is a problem with how Intel ARC presents its PCIe bridge information.

# lspci -s b5:00.0 -vv
b5:00.0 VGA compatible controller: Intel Corporation Battlemage G21 [Intel Graphics] (prog-if 00 [VGA controller])
        Subsystem: Intel Corporation Device 1114
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 32 bytes
        Interrupt: pin ? routed to IRQ 185
        NUMA node: 0
        IOMMU group: 4
        Region 0: Memory at fa000000 (64-bit, non-prefetchable) [size=16M]
        Region 2: Memory at 38f800000000 (64-bit, prefetchable) [size=16G]
        Expansion ROM at fb000000 [disabled] [size=2M]
        Capabilities: [40] Vendor Specific Information: Len=0c <?>
        Capabilities: [70] Express (v2) Endpoint, IntMsgNum 0
                DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited
                        ExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset+ SlotPowerLimit 0W TEE-IO-
                DevCtl: CorrErr- NonFatalErr- FatalErr+ UnsupReq-
                        RlxdOrd+ ExtTag+ PhantFunc- AuxPwr- NoSnoop+ FLReset-
                        MaxPayload 256 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <64ns, L1 <1us
                        ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp+
                LnkCtl: ASPM Disabled; RCB 64 bytes, LnkDisable- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1
                        TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-

Find out what bridge b5:00.0 is attached to, in my case b2:00.0

# lspci -s b5:00.0 -tv
-[0000:b2]---00.0-[b3-b6]----00.0-[b4-b6]----01.0-[b5]----00.0  Intel Corporation Battlemage G21 [Intel Graphics]

The link state is the expected Speed 8GT/s, Width x8.

lspci -s b2:00.0 -vv
b2:00.0 PCI bridge: Intel Corporation Sky Lake-E PCI Express Root Port A (rev 07) (prog-if 00 [Normal decode])
        Subsystem: Super Micro Computer Inc Device 095e
        Physical Slot: 9
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 36
        NUMA node: 0
        IOMMU group: 0
        Bus: primary=b2, secondary=b3, subordinate=b6, sec-latency=0
        I/O behind bridge: [disabled] [16-bit]
        Memory behind bridge: fa000000-fb3fffff [size=20M] [32-bit]
        Prefetchable memory behind bridge: 38f800000000-38fc007fffff [size=16392M] [32-bit]
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR+ NoISA- VGA+ VGA16+ MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Subsystem: Super Micro Computer Inc Device 095e
        Capabilities: [60] MSI: Enable+ Count=1/2 Maskable+ 64bit-
                Address: fee00038  Data: 0000
                Masking: 00000002  Pending: 00000000
        Capabilities: [90] Express (v2) Root Port (Slot+), IntMsgNum 0
                DevCap: MaxPayload 256 bytes, PhantFunc 0
                        ExtTag+ RBE+ TEE-IO-
                DevCtl: CorrErr- NonFatalErr- FatalErr+ UnsupReq-
                        RlxdOrd- ExtTag+ PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 256 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr- TransPend-
                LnkCap: Port #9, Speed 8GT/s, Width x16, ASPM L1, Exit Latency L1 <16us
                        ClockPM- Surprise+ LLActRep+ BwNot+ ASPMOptComp+
                LnkCtl: ASPM Disabled; RCB 64 bytes, LnkDisable- CommClk+
                        ExtSynch- ClockPM- AutWidDis- BWInt+ AutBWInt+
                LnkSta: Speed 8GT/s, Width x8
                        TrErr- Train- SlotClk+ DLActive+ BWMgmt- ABWMgmt-

Enabling Virtual Functions

Sadly the current B50 drivers limits the number of VFs to 2, so that is all you get:

b5:00.0 VGA compatible controller: Intel Corporation Battlemage G21 [Intel Graphics]
b5:00.1 VGA compatible controller: Intel Corporation Battlemage G21 [Intel Graphics]
b5:00.2 VGA compatible controller: Intel Corporation Battlemage G21 [Intel Graphics]

What’s next?

So I’m almost there, this next step is actually getting what I actually want set up.

  • Creating a VM for LLM and OpenWebUI and passing through one of the VFs
  • Making it all work :smiley:

Not sure which LLM server to use for the B50, I have heard that vllm is supposed to have good support for it. Is this correct? Any recommendations?

I you have questions please ask, I’ll try to supply more details if and as required.

1 Like

I found the time to get it up and running.

Here is the compose.yaml

---
services:
  llamacpp-server:
    image: ghcr.io/ggml-org/llama.cpp:server-intel
    container_name: llamacpp-server
    restart: unless-stopped
    networks:
      - caddy
    labels:
      caddy: llama.home.net
      caddy.reverse_proxy: llamacpp-server:8081
      caddy.import: acme-rfc2136
    ports:
      - 8081:8081
    volumes:
      - /mnt/services/docker/data/llama/models:/models
    devices:
      - /dev/dri/:/dev/dri/
    group_add:
      - "993" # render group
      - "44"  # video group
    environment:
      - SYCL_DEVICE_FILTER=level_zero:gpu
      - ONEAPI_DEVICE_SELECTOR=level_zero:gpu
      - GGML_SYCL_FORCE_MMQ=1
      - LLAMA_ARG_N_GPU_LAYERS=99
    command: >
      --models-dir /models
      --host 0.0.0.0
      --port 8081
      --model /models/Qwen3.5-9B-GGUF/Qwen_Qwen3.5-9B-Q4_K_M.gguf
      --ctx-size 32768

networks:
  caddy:
    external: true
...

This was my first time running a local LLM so where and how to DL a model took some figuring out, I ended up doing this (I’m sure there must be a better way):

docker run --rm -it -v /mnt/services/docker/data/llama/models\:/models \
 netspeedy/huggingface-cli \
download bartowski/Qwen_Qwen3.5-9B-GGUF \
--local-dir /models/Qwen3.5-9B-GGUF

I’m getting about 30 tokens/s, which seems to be about right.

Local LLM :white_check_mark:

Now to start playing :smiley:

Niiiice. I run a somewhat similar set up. Except I’m on an Asus c246 Pro motherboard- but using the B50 has been fun. I may steal and adapt your script this weekend.

1 Like