fix(ghal): support JD Cloud 4096-entry queues

Seal physical probe failures as FAIL_0 receipts, clear consumed proof only through an authorized receipt, and isolate each legacy virtqueue in a 128 KiB region sized for JD Cloud.
This commit is contained in:
冰朔 2026-08-03 21:07:06 +08:00
commit e52843f4de
4 changed files with 131 additions and 37 deletions

View file

@ -112,6 +112,14 @@ Native build scripts derive their NASM addresses from
`WORLD-MANIFEST.hldp`; the traditional bootstrap code no longer owns fixed
Shanghai sector numbers.
The first JD one-time physical probe reached the native kernel and returned to
Linux with a sealed `FAIL_0` diagnostic: the cloud virtio-net RX queue exposes
4096 entries, while the inherited GHAL allocation accepted at most 1024. The
JD adapter therefore assigns a non-overlapping 128 KiB region to each legacy
queue and accepts the observed 4096-entry maximum. A failed probe remains a
failure; its LBA 134 proof must be sealed and cleared with
`clear-jd-native-probe-proof.sh` before an exact-hardware retry.
## Hosted Stage 1 installation
`scripts/install-hosted-stage1.sh` is the repeatable Ubuntu construction

View file

@ -21,14 +21,14 @@ bits 64
%define VIRTIO_NET_F_MAC 5
%define VIRTIO_NET_RX_QUEUE 0x100000
%define VIRTIO_NET_TX_QUEUE 0x108000
%define VIRTIO_BLOCK_QUEUE 0x110000
%define VIRTIO_NET_RX_BUFFER 0x120000
%define VIRTIO_NET_TX_BUFFER 0x121000
%define VIRTIO_BLOCK_READ_BUFFER 0x122000
%define VIRTIO_CODE_CHANNEL_BUFFER 0x123000
%define VIRTIO_RECOVERY_BEACON_BUFFER 0x124000
%define VIRTIO_GESTATIONAL_INDEX_BUFFER 0x125000
%define VIRTIO_NET_TX_QUEUE 0x120000
%define VIRTIO_BLOCK_QUEUE 0x140000
%define VIRTIO_NET_RX_BUFFER 0x160000
%define VIRTIO_NET_TX_BUFFER 0x161000
%define VIRTIO_BLOCK_READ_BUFFER 0x162000
%define VIRTIO_CODE_CHANNEL_BUFFER 0x163000
%define VIRTIO_RECOVERY_BEACON_BUFFER 0x164000
%define VIRTIO_GESTATIONAL_INDEX_BUFFER 0x165000
%define VIRTIO_NET_BUFFER_SIZE 2048
%define VIRTIO_NET_HEADER_SIZE 10
%define ETHERNET_HEADER_SIZE 14
@ -36,8 +36,26 @@ bits 64
%define ICMP_HEADER_SIZE 8
%define GHOS_LOGIN_MAGIC_OFFSET 60
%define GHOS_LOGIN_MAGIC_SIZE 16
%define VIRTIO_QUEUE_BYTES 0x8000
%define VIRTIO_MAX_QUEUE_SIZE 1024
; JD Cloud exposes 4096-entry legacy queues. A queue of that size occupies
; 0x1b004 bytes after descriptor, available, page alignment, and used rings,
; so every queue receives an isolated 0x20000-byte region.
%define VIRTIO_QUEUE_BYTES 0x20000
%define VIRTIO_MAX_QUEUE_SIZE 4096
%define VIRTIO_MAX_USED_RING_END \
(((18 * VIRTIO_MAX_QUEUE_SIZE + 6 + 4095) & ~4095) + \
8 * VIRTIO_MAX_QUEUE_SIZE + 6)
%if VIRTIO_MAX_USED_RING_END > VIRTIO_QUEUE_BYTES
%error "legacy virtqueue region is smaller than the registered maximum queue"
%endif
%if VIRTIO_NET_TX_QUEUE - VIRTIO_NET_RX_QUEUE < VIRTIO_QUEUE_BYTES
%error "virtio-net RX and TX queue regions overlap"
%endif
%if VIRTIO_BLOCK_QUEUE - VIRTIO_NET_TX_QUEUE < VIRTIO_QUEUE_BYTES
%error "virtio-net TX and virtio-block queue regions overlap"
%endif
%if VIRTIO_NET_RX_BUFFER - VIRTIO_BLOCK_QUEUE < VIRTIO_QUEUE_BYTES
%error "virtio-block queue overlaps native I/O buffers"
%endif
%define VIRTQ_DESC_F_NEXT 1
%define VIRTQ_DESC_F_WRITE 2
%define VIRTIO_BLK_T_IN 0

View file

@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -euo pipefail
[[ $# -eq 2 ]] || {
echo "usage: clear-jd-native-probe-proof.sh <world-root> <recovery-root>" >&2
exit 64
}
[[ ${EUID} -eq 0 ]] || exit 77
world_root=$(readlink -f "$1")
recovery_root=$(readlink -f "$2")
grep -q '^node_id: JD-FD-PRIMARY$' "${world_root}/CURRENT.hldp"
grep -q '^status: FAIL_0$' "${recovery_root}/RETURN-RECEIPT.hldp"
grep -q '^ proof_lba: 134$' "${recovery_root}/RETURN-RECEIPT.hldp"
/guanghu/bin/ghctl authorize "${world_root}" \
write_bootloader_and_system_partitions >/dev/null
proof=${recovery_root}/lba134.native-proof.bin
expected_sha=$(awk '/^ proof_sha256:/ {print $2}' \
"${recovery_root}/RETURN-RECEIPT.hldp")
[[ ${expected_sha} =~ ^[0-9a-f]{64}$ ]]
[[ $(sha256sum "${proof}" | awk '{print $1}') == "${expected_sha}" ]]
[[ $(dd if=/dev/vda bs=512 skip=134 count=1 status=none | sha256sum |
awk '{print $1}') == "${expected_sha}" ]]
dd if=/dev/zero of=/dev/vda bs=512 seek=134 count=1 conv=notrunc,fsync \
status=none
zero_sha=$(head -c 512 /dev/zero | sha256sum | awk '{print $1}')
readback_sha=$(dd if=/dev/vda bs=512 skip=134 count=1 status=none |
sha256sum | awk '{print $1}')
[[ ${readback_sha} == "${zero_sha}" ]]
observed_at=$(date --iso-8601=seconds)
cat >"${recovery_root}/PROOF-CLEAR-RECEIPT.hldp" <<EOF
schema: guanghu.jd-native-probe-proof-clear/v1
receipt_id: GH-OS-JD-FD-PRIMARY-001-PROBE-PROOF-CLEAR
status: PASS_100
observed_at: ${observed_at}
node_id: JD-FD-PRIMARY
proof:
lba: 134
sealed_sha256: ${expected_sha}
zero_readback_sha256: ${readback_sha}
reason: SEALED_FAIL_0_CONSUMED_BEFORE_EXACT_HARDWARE_ADAPTER_RETRY
EOF
chmod 0400 "${recovery_root}/PROOF-CLEAR-RECEIPT.hldp"
cat "${recovery_root}/PROOF-CLEAR-RECEIPT.hldp"

View file

@ -16,50 +16,71 @@ grep -q '^status: ARMED_FOR_ONE_BOOT$' "${recovery_root}/ARM-RECEIPT.hldp"
before_boot_id=$(<"${recovery_root}/linux-boot-id.before")
after_boot_id=$(</proc/sys/kernel/random/boot_id)
[[ ${before_boot_id} != "${after_boot_id}" ]]
if grub-editenv /boot/grub/grubenv list | grep -q '^next_entry='; then
if grub-editenv /boot/grub/grubenv list | grep -Eq '^next_entry=.+$'; then
echo "one-time GRUB entry was not consumed" >&2
exit 65
fi
proof=$(mktemp)
trap 'rm -f "${proof}"' EXIT
proof=${recovery_root}/lba134.native-proof.bin
receipt=${recovery_root}/RETURN-RECEIPT.hldp
dd if=/dev/vda of="${proof}" bs=512 skip=134 count=1 status=none
python3 - "${proof}" <<'PY'
observed_at=$(date --iso-8601=seconds)
python3 - "${proof}" "${receipt}" "${observed_at}" \
"${before_boot_id}" "${after_boot_id}" <<'PY'
import hashlib
import pathlib
import sys
proof = pathlib.Path(sys.argv[1]).read_bytes()
assert len(proof) == 512
assert proof[0] == 0xA5
assert proof[1:].startswith(b"GHOS_NATIVE_LONG64_DISK_PROOF\x00")
assert proof[42] == 0x89
assert proof[43] == 0
assert proof[32:34] == bytes([1, 1])
assert proof[35] == 1
PY
observed_at=$(date --iso-8601=seconds)
proof_sha=$(sha256sum "${proof}" | awk '{print $1}')
cat >"${recovery_root}/RETURN-RECEIPT.hldp" <<EOF
schema: guanghu.jd-native-probe-return/v1
proof_path = pathlib.Path(sys.argv[1])
receipt_path = pathlib.Path(sys.argv[2])
observed_at, before_boot_id, after_boot_id = sys.argv[3:]
proof = proof_path.read_bytes()
assert len(proof) == 512
assert proof[1:].startswith(b"GHOS_NATIVE_LONG64_DISK_PROOF\x00")
stage = proof[42]
error = proof[43]
success = (
proof[0] == 0xA5
and stage == 0x89
and error == 0
and proof[32:34] == bytes([1, 1])
and proof[35] == 1
)
u16 = lambda offset: int.from_bytes(proof[offset:offset + 2], "little")
status = "PASS_100" if success else "FAIL_0"
next_action = (
"PHYSICAL_NETWORK_AND_RESIDENT_RUNTIME_GATE"
if success
else "SEAL_FAILURE_CLEAR_PROOF_AND_REBUILD_EXACT_HARDWARE_ADAPTER"
)
receipt_path.write_text(f"""schema: guanghu.jd-native-probe-return/v1
receipt_id: GH-OS-JD-FD-PRIMARY-001-PROBE-RETURN
status: PASS_100
observed_at: ${observed_at}
status: {status}
observed_at: {observed_at}
node_id: JD-FD-PRIMARY
boot:
linux_boot_id_before: ${before_boot_id}
linux_boot_id_after: ${after_boot_id}
linux_boot_id_before: {before_boot_id}
linux_boot_id_after: {after_boot_id}
one_time_entry_consumed: true
native_probe:
stage: 9
proof_lba: 134
proof_sha256: ${proof_sha}
legacy_bios_long_mode: true
virtio_block_queue: true
proof_sha256: {hashlib.sha256(proof).hexdigest()}
proof_flag: 0x{proof[0]:02x}
observed_stage: 0x{stage:02x}
observed_error: 0x{error:02x}
virtio_net_queue_size: {u16(44)}
virtio_net_tx_queue_size: {u16(46)}
virtio_block_queue_size: {u16(48)}
legacy_bios_long_mode: {str(proof[0] in (0xA5, 0xE1)).lower()}
virtio_block_queue: {str(bool(proof[35])).lower()}
hardware_reset_to_linux_rescue: true
boundary:
network_and_resident_runtime_proven: false
native_default_proven: false
next_action: PHYSICAL_NETWORK_AND_RESIDENT_RUNTIME_GATE
EOF
chmod 0400 "${recovery_root}/RETURN-RECEIPT.hldp"
cat "${recovery_root}/RETURN-RECEIPT.hldp"
next_action: {next_action}
""")
PY
chmod 0400 "${proof}" "${receipt}"
cat "${receipt}"
grep -q '^status: PASS_100$' "${receipt}"