eve-kvm:core-isolation
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| eve-kvm:core-isolation [2026/09/18 16:47] – mc | eve-kvm:core-isolation [2026/09/19 17:35] (current) – mc | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== EVE CPU Core Pinning and Isolation ====== | + | ====== EVE CPU Core Isolation |
| - | How to enable kernel CPU isolation on an EVE node, prove it took effect, and demo it. | + | Follow the steps in order. Every step has a command, the output you should see, and what to do if you do not see it. Do not skip **Step 5** (the BEFORE baseline) — it is what makes the AFTER checks meaningful. |
| - | **Scope.** | + | **Scope.** |
| - | **Provenance.** The transcripts in §3, §4.1 and §4.4 were captured on a live node on 2026-09-18. The outputs | + | **Time required.** About 20 minutes, including one reboot. |
| + | |||
| + | **Just here to run the demo?** Use the four-act script immediately below. The numbered steps in Parts 1-4 are the full procedure behind it. | ||
| ---- | ---- | ||
| - | ===== 1. Requirements | + | ===== Quick demo script — 1, 2, 3, 4 ===== |
| - | ==== 1.1 CPU ==== | + | Four commands-and-a-sentence. Run them in order, with the pinned VM **not yet deployed**. |
| - | Pinning on this branch means **whole-core SMT**: each vCPU gets one hardware thread of a physical core, and both siblings go to the same workload. The allocator will only use a core that has **exactly two hardware threads**. | + | Set this up first so every command is a single keystroke away: |
| - | * **SMT / Hyper-Threading | + | <code bash> |
| - | * At least **3 physical cores** to be useful: one for EVE housekeeping, one for the dedicated pool, one or more to isolate. | + | alias iso=' |
| - | * Even vCPU counts only. An odd count fails closed with '' | + | alias pools=' |
| - | * Homogeneous | + | alias plan=' |
| + | alias ticks=' | ||
| + | </ | ||
| + | |||
| + | ==== 1. BEFORE — a plain node: no isolation, no assignment ==== | ||
| + | |||
| + | <code bash> | ||
| + | iso | ||
| + | pools | ||
| + | ticks | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | isolated: [] | ||
| + | {" | ||
| + | {" | ||
| + | cpu0=73851 | ||
| + | </ | ||
| + | |||
| + | **Say:** "The kernel isolates nothing. There is one pool — all eight threads, shared. Every CPU is doing work. Any workload can be scheduled anywhere, and so can the kernel' | ||
| + | |||
| + | //This is the state before any configuration. If your node is already configured and you want to rehearse the whole arc, revert it with:// '' | ||
| + | |||
| + | ==== 2. AFTER the config — the isolated pool exists, and nobody may use it ==== | ||
| + | |||
| + | Enable per Part 2 (property, '' | ||
| + | |||
| + | <code bash> | ||
| + | iso | ||
| + | pools | ||
| + | ticks | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | isolated: [4-7] | ||
| + | {" | ||
| + | {" | ||
| + | {" | ||
| + | cpu0=9525 | ||
| + | </ | ||
| + | |||
| + | **Say:** " | ||
| + | |||
| + | **Point at:** '' | ||
| + | |||
| + | ==== 3. DEPLOY — a pinned VM takes an isolated core ==== | ||
| + | |||
| + | Deploy a **2-vCPU** app with CPU pinning enabled, then: | ||
| + | |||
| + | <code bash> | ||
| + | plan | ||
| + | pools | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | { " | ||
| + | " | ||
| + | |||
| + | {" | ||
| + | {" | ||
| + | {" | ||
| + | </ | ||
| + | |||
| + | **Say:** "Two vCPUs, | ||
| + | |||
| + | ==== 4. PROVE IT — the kernel agrees, down to the thread ==== | ||
| + | |||
| + | <code bash> | ||
| + | PID=$(pgrep -f qemu-system | head -1) | ||
| + | for t in / | ||
| + | printf '%-18s %s | ||
| + | ' "$(cat $t/ | ||
| + | done | sort -u | ||
| + | cat / | ||
| + | ticks | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | qemu-system-x86 | ||
| + | qemu-system-x86 | ||
| + | qemu-system-x86 | ||
| + | vhost-7981 | ||
| + | |||
| + | 4-5 | ||
| + | |||
| + | cpu0=9525 | ||
| + | </ | ||
| + | |||
| + | **Say:** " | ||
| + | |||
| + | **The closing line:** cores 6 and 7 are idle and cannot be used by anything that did not ask for isolation. On this node, a workload that needs guaranteed CPU gets it — not by priority, not by best effort, but because nothing else is allowed to run there. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Part 0 — Understand what you are doing ===== | ||
| + | |||
| + | There are **two independent switches**. Neither works without the other. | ||
| + | |||
| + | ^ # ^ Switch ^ Where it is set ^ What it does ^ Needs reboot? ^ | ||
| + | | 1 | '' | ||
| + | | 2 | '' | ||
| + | |||
| + | A third thing is often confused with these: | ||
| + | |||
| + | * **"CPU pinning" | ||
| + | |||
| + | Target layout on a 4-core / 8-thread node: | ||
| + | |||
| + | ^ Role ^ Physical core ^ CPUs ^ | ||
| + | | EVE housekeeping | core 0 | 0, 1 | | ||
| + | | Dedicated pool (ordinary pinned workloads) | core 1 | 2, 3 | | ||
| + | | **Isolated pool** | cores 2-3 | **4, 5, 6, 7** | | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Part 1 — BEFORE: prerequisites and baseline ===== | ||
| + | |||
| + | Run every command in this part **on the node**, over SSH or the console, before changing anything. | ||
| + | |||
| + | ==== Step 1 — Confirm the CPU can do this ==== | ||
| + | |||
| + | <code bash> | ||
| + | lscpu | grep -E 'Model name|Thread\(s\) per core|Core\(s\) per socket|NUMA node\(s\)' | ||
| + | </ | ||
| + | |||
| + | Expected: | ||
| + | |||
| + | < | ||
| + | Model name: 13th Gen Intel(R) Core(TM) i3-13100TE | ||
| + | Thread(s) per core: 2 | ||
| + | Core(s) per socket: | ||
| + | NUMA node(s): | ||
| + | </ | ||
| + | |||
| + | **PASS if '' | ||
| + | |||
| + | You also need **at least 3 physical cores**: one for EVE, one for the dedicated pool, one to isolate. | ||
| ^ CPU ^ Topology ^ Usable ^ | ^ CPU ^ Topology ^ Usable ^ | ||
| Line 28: | Line 166: | ||
| | Core Ultra 200S / Meteor Lake / Lunar Lake | SMT removed | **no** | | | Core Ultra 200S / Meteor Lake / Lunar Lake | SMT removed | **no** | | ||
| - | Reference node for this page: **Intel Core i3-13100TE**, | + | Avoid Intel hybrid parts with E-cores |
| - | ==== 1.2 Check the node before you start ==== | + | ==== Step 2 — Find out which CPUs are SMT siblings |
| + | |||
| + | This decides the numbers you will type in Step 8. **Do not assume them.** | ||
| <code bash> | <code bash> | ||
| - | lscpu | grep -E 'Model name|Thread\(s\) per core|Core\(s\) per socket|NUMA node\(s\)' | + | cat / |
| </ | </ | ||
| - | '' | + | Expected on the reference node: |
| - | ---- | + | < |
| + | 0-1 | ||
| + | 2-3 | ||
| + | 4-5 | ||
| + | 6-7 | ||
| + | </ | ||
| - | ===== 2. Enable core isolation ===== | + | ^ If you see ^ Enumeration ^ Use the values in ^ |
| + | | '' | ||
| + | | '' | ||
| - | ==== 2.1 Determine the SMT sibling enumeration | + | ==== Step 3 — Confirm nothing is isolated yet ==== |
| - | This decides your CPU indexes. Do not assume | + | <code bash> |
| + | cat / | ||
| + | </ | ||
| + | |||
| + | Expected: **empty output.** That is the starting state. If it already lists CPUs, someone has been here before — read the existing ''/ | ||
| + | |||
| + | ==== Step 4 — Confirm the property is currently off ==== | ||
| <code bash> | <code bash> | ||
| - | cat / | + | grep -o 'cpu.pinning.use.isolated[^}]*}' |
| </ | </ | ||
| - | Two possible answers on a 4C/8T part: | + | Expected: |
| - | ^ Output ^ Meaning ^ Core map ^ | + | < |
| - | | '' | + | cpu.pinning.use.isolated": |
| - | | '' | + | </ |
| - | ==== 2.2 Decide | + | '' |
| - | Three roles. The isolated set **must be sibling-complete** | + | ==== Step 5 — Capture |
| - | ^ Role ^ Cores ^ CPUs (adjacent enumeration) ^ | + | Paste this whole block. Save the output somewhere; you will compare against it in Step 12. |
| - | | EVE housekeeping | core 0 | 0,1 | | + | |
| - | | Dedicated pool (ordinary pinned workloads) | core 1 | 2,3 | | + | |
| - | | Isolated pool | cores 2-3 | 4,5,6,7 | | + | |
| - | ==== 2.3 Set the controller property | + | <code bash> |
| + | echo "=== cmdline | ||
| + | tr ' ' ' | ||
| + | echo "=== kernel isolated set ===" | ||
| + | echo " | ||
| + | echo "=== CPU pools ===" | ||
| + | cat / | ||
| + | echo "=== placement plan ===" | ||
| + | cat / | ||
| + | echo "=== eve cpuset ===" | ||
| + | cat / | ||
| + | echo "=== per-CPU busy ticks ===" | ||
| + | awk '/ | ||
| + | </ | ||
| + | |||
| + | Expected BEFORE (no isolation, nothing pinned): | ||
| + | |||
| + | < | ||
| + | === cmdline === | ||
| + | eve_max_vcpus=1 | ||
| + | === kernel isolated set === | ||
| + | [] | ||
| + | === CPU pools === | ||
| + | {" | ||
| + | | ||
| + | | ||
| + | | ||
| + | ]} | ||
| + | === eve cpuset === | ||
| + | 0 | ||
| + | </ | ||
| + | |||
| + | Pool '' | ||
| + | |||
| + | What this baseline says: all 8 threads are in housekeeping, | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Part 2 — ENABLE ===== | ||
| + | |||
| + | Do these three steps **in this order**. Doing the property last costs you a second reboot. | ||
| + | |||
| + | ==== Step 6 — Set the controller property ==== | ||
| + | |||
| + | **This property is not exposed in the ZedControl UI.** Do not go looking for it there — the UI only offers properties it knows about, and this one is new in the feature branch. It can only be set via **Terraform** or the **REST API**. | ||
| + | |||
| + | **Terraform** — a '' | ||
| + | |||
| + | < | ||
| + | resource " | ||
| + | # ... existing fields ... | ||
| + | |||
| + | config_item { | ||
| + | key = " | ||
| + | string_value = " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Then '' | ||
| + | |||
| + | **Use '' | ||
| + | |||
| + | ^ Hop ^ Schema ^ Fields ^ | ||
| + | | you → controller | '' | ||
| + | | controller → device | eve-api '' | ||
| + | |||
| + | The controller has to collapse the typed fields into a single string '' | ||
| + | |||
| + | **REST** — '' | ||
| + | |||
| + | <code javascript> | ||
| + | { " | ||
| + | </ | ||
| + | |||
| + | **This is a full-object PUT, not a patch.** The body carries the whole edge node — '' | ||
| + | |||
| + | So the REST procedure is read-modify-write: | ||
| + | |||
| + | - '' | ||
| + | - append '' | ||
| + | - '' | ||
| + | |||
| + | This is why Terraform is the easier route: the provider does that read-modify-write for you. Schema verified against '' | ||
| + | |||
| + | **Do not expect to find the key itself in the API documentation.** In the spec '' | ||
| + | |||
| + | Whichever route you use, **Step 7 is what confirms it** — do not assume it landed. | ||
| + | |||
| + | ==== Step 7 — Confirm the property reached the node ==== | ||
| + | |||
| + | Do not go further until this passes. Allow a minute for the config poll. | ||
| + | |||
| + | <code bash> | ||
| + | grep -o ' | ||
| + | logread | grep ' | ||
| + | </ | ||
| - | In the controller, set the edge-node configuration property: | + | Expected: |
| < | < | ||
| - | cpu.pinning.use.isolated | + | " |
| + | domainmgr: CPU placement: | ||
| </ | </ | ||
| - | **Order matters.** Set this //before// the reboot that applies | + | **If '' |
| - | Without this property, kernel-isolated CPUs are reported in the pool report and usable by **nobody**: they are withheld from every workload that did not explicitly ask for isolation, and only '' | + | ==== Step 8 — Write / |
| - | ==== 2.4 Write / | + | '' |
| - | ''/ | + | === Step 8a — adjacent siblings (0-1, 2-3, 4-5, 6-7) === |
| <code bash> | <code bash> | ||
| Line 93: | Line 340: | ||
| </ | </ | ||
| - | For the **split** enumeration use '' | + | === Step 8b — split siblings (0,4 1,5 |
| - | Notes: | + | <code bash> |
| + | eve config mount /tmp/cfg | ||
| + | cat > / | ||
| + | set_getty | ||
| + | set_global dom0_extra_args " | ||
| + | EOF | ||
| + | cat / | ||
| + | sync | ||
| + | eve config unmount | ||
| + | </ | ||
| - | | + | There is **no '' |
| - | | + | |
| - | * '' | + | |
| - | * Do **not** use GRUB's '' | + | |
| - | * ''/ | + | |
| - | ==== 2.5 Reboot ==== | + | **Check the '' |
| + | |||
| + | Rules that matter here: | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * Do **not** use GRUB's '' | ||
| + | |||
| + | ==== Step 9 — Reboot ==== | ||
| <code bash> | <code bash> | ||
| Line 109: | Line 369: | ||
| </ | </ | ||
| - | Kernel isolation | + | Allow about 3 minutes. The reboot is required for two reasons: '' |
| + | |||
| + | Expect | ||
| ---- | ---- | ||
| - | ===== 3. Validate | + | ===== Part 3 — AFTER: validate |
| - | Run these in order. Stop at the first one that disagrees. | + | Run these in order. Stop at the first failure. |
| - | ==== 3.1 The kernel accepted the arguments ==== | + | ==== Step 10 — The kernel accepted the arguments ==== |
| <code bash> | <code bash> | ||
| Line 131: | Line 393: | ||
| </ | </ | ||
| - | ==== 3.2 The kernel is actually isolating ==== | + | **If nothing appears:** GRUB never read your file. Confirm it is named '' |
| + | |||
| + | ==== Step 11 — The kernel is actually isolating ==== | ||
| <code bash> | <code bash> | ||
| Line 141: | Line 405: | ||
| </ | </ | ||
| - | **An empty result means there is no isolated pool and nothing | + | **This is the make-or-break check.** An empty result means there is no isolated pool and nothing |
| - | ==== 3.3 domainmgr saw the topology and the isolated set ==== | + | ==== Step 12 — domainmgr saw the topology and the isolated set ==== |
| <code bash> | <code bash> | ||
| Line 154: | Line 418: | ||
| </ | </ | ||
| - | '' | + | '' |
| - | Note: the second line is printed whenever the isolated set is non-empty, | + | Ignore the wording of the second line — it is printed whenever the isolated set is non-empty, |
| - | ==== 3.4 The pool report | + | ==== Step 13 — The pools changed |
| <code bash> | <code bash> | ||
| cat / | cat / | ||
| </ | </ | ||
| - | |||
| - | Pool '' | ||
| <code javascript> | <code javascript> | ||
| {" | {" | ||
| | | ||
| - | | + | |
| | | ||
| ]} | ]} | ||
| </ | </ | ||
| - | What to read from it: | + | ==== Step 14 — BEFORE vs AFTER at a glance ==== |
| - | * **Kind 3 is non-empty** — the isolated set is now allocatable capacity, not just a number in the device info. | + | ^ Check ^ BEFORE ^ AFTER ^ |
| - | * **Kind 1 '' | + | | '' |
| - | * **Kind 1 '' | + | | '' |
| + | | Isolated pool (Kind 3) | does not exist | '' | ||
| + | | Housekeeping free CPUs (Kind 1) | '' | ||
| + | | Housekeeping free whole cores | 3 | 1 | | ||
| - | ==== 3.5 The promotion switch ==== | + | The housekeeping line is the one to point at. Of 8 threads, 6 are now allocated: CPUs 0-1 reserved for EVE and CPUs 4-7 withheld for isolation. Only core 1 is left for an ordinary workload. That is the feature working: housekeeping freeness answers //" |
| - | <code bash> | + | ==== Step 15 — Nothing is running on the isolated cores ==== |
| - | grep -o ' | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | cpu.pinning.use.isolated": | + | |
| - | </ | + | |
| - | + | ||
| - | '' | + | |
| - | + | ||
| - | ==== 3.6 Derived placement plan ==== | + | |
| <code bash> | <code bash> | ||
| - | cat /run/domainmgr/ | + | awk '/^cpu[4-7] |
| - | </ | + | |
| - | + | ||
| - | <code javascript> | + | |
| - | { | + | |
| - | " | + | |
| - | { " | + | |
| - | " | + | |
| - | ] | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Diagnostic only — nothing reads it back — but it is the quickest way to see what the allocator decided, including for workloads that are configured but not running. | + | |
| - | + | ||
| - | ==== 3.7 Known limitations on the shipped kernel ==== | + | |
| - | + | ||
| - | ^ Argument ^ Effect ^ Why ^ | + | |
| - | | '' | + | |
| - | | '' | + | |
| - | | '' | + | |
| - | | '' | + | |
| - | + | ||
| - | <code bash> | + | |
| - | dmesg | grep -iE ' | + | |
| - | (zcat /proc/config.gz || cat / | + | |
| </ | </ | ||
| < | < | ||
| - | Housekeeping: | + | cpu4 0 |
| - | Unknown kernel command line parameters "... rcu_nocbs=4, | + | cpu5 0 |
| - | # CONFIG_NO_HZ_FULL is not set | + | cpu6 0 |
| - | CONFIG_CPU_ISOLATION=y | + | cpu7 0 |
| </ | </ | ||
| - | So today you get the '' | + | Zero busy ticks since boot. Keep this number |
| - | + | ||
| - | Two more expected observations: | + | |
| - | + | ||
| - | * **''/ | + | |
| - | * **The vault reports a PCR mismatch.** Changing | + | |
| ---- | ---- | ||
| - | ===== 4. Demo ===== | + | ===== Part 4 — Demo ===== |
| - | + | ||
| - | Four steps, each one showing a distinct guarantee. Run §3 first so you are demoing from a known-good base. | + | |
| - | + | ||
| - | ==== 4.1 An ordinary pinned workload avoids the isolated cores ==== | + | |
| - | With '' | + | ==== Step 16 — A pinned workload lands on the isolated |
| - | Expected: it lands on the **dedicated** pool — CPUs 2,3 — and never on 4-7. | + | Deploy a **2-vCPU** app with CPU pinning enabled (even vCPU counts only — an odd count fails closed with '' |
| <code bash> | <code bash> | ||
| Line 254: | Line 476: | ||
| <code javascript> | <code javascript> | ||
| - | { " | + | { " |
| - | | + | |
| {" | {" | ||
| - | | + | |
| - | | + | |
| - | | + | |
| ]} | ]} | ||
| </ | </ | ||
| - | Kind 2 (dedicated) becomes | + | Read it as: the isolated pool went from 2 free whole cores to 1, the dedicated |
| - | Note that a legacy | + | Worth saying out loud during |
| - | ==== 4.2 Capacity fails closed | + | ==== Step 17 — Capacity fails closed |
| - | Deploy a **second** 2-vCPU pinned app on the same node. | + | //Not yet captured |
| - | Expected: it **fails** rather than taking an isolated core, and the error states how many cores were withheld for isolation | + | With the switch |
| - | This is the demo that makes the point: the node has 4 free threads at that moment and still refuses, //by design//. | + | With the switch **off**, it is the //second// app that fails, for the same reason. |
| - | ==== 4.3 The node-wide switch promotes a pinned workload ==== | + | The error names how many cores were withheld for isolation, so the operator is not left comparing " |
| - | Set '' | + | ==== Step 18 — Prove it at the thread level ==== |
| - | Expected: the same 2-vCPU pinned app is now placed on **4,5** (or 6,7). A controller that can only send '' | + | The pool report |
| <code bash> | <code bash> | ||
| - | cat /run/domainmgr/cpuplan.json | + | ls /run/hypervisor/kvm/ |
| + | PID=$(pgrep -f qemu-system | head -1) | ||
| + | for t in / | ||
| + | printf '%-18s %s\n' "$(cat $t/ | ||
| + | done | sort -u | ||
| + | find / | ||
| + | awk '/^cpu[0-9] /{print $1, $2+$4}' | ||
| </ | </ | ||
| - | Only whole-core workloads are promoted: kernel isolation means nothing on a core whose sibling the kernel still schedules freely. | + | < |
| + | qemu-system-x86 | ||
| + | qemu-system-x86 | ||
| + | qemu-system-x86 | ||
| + | vhost-7981 | ||
| + | iou-wrk-7981 | ||
| - | ==== 4.4 Prove it at the thread level ==== | + | /sys/fs/cgroup/cpuset/eve-user-apps/ |
| - | + | ||
| - | The pool report is EVE's own bookkeeping. This shows the kernel agrees. | + | |
| - | + | ||
| - | <code bash> | + | |
| - | # find the domain | + | |
| - | ls /run/hypervisor/kvm/ # <app-uuid>.<gen>.< | + | |
| - | PID=$(pgrep -f '< | + | |
| - | # per-thread affinity of the VM's vCPU threads | + | cpu4 1990 cpu5 813 cpu6 0 cpu7 0 |
| - | for t in / | + | |
| - | printf ' | + | |
| - | done | + | |
| </ | </ | ||
| - | Captured on the dedicated-pool run of §4.1 (2 vCPUs on core 1): | + | The two vCPU threads are pinned **1:1** to CPUs 4 and 5; everything else is confined to '' |
| - | < | + | ==== Step 19 — One-shot cross-check ==== |
| - | qemu pid=8752 | + | |
| - | qemu-system-x86 2-3 | + | |
| - | qemu-system-x86 | + | |
| - | qemu-system-x86 | + | |
| - | trace-thread | + | |
| - | vhost-8752 | + | |
| - | iou-wrk-8752 | + | |
| - | </ | + | |
| - | The two vCPU threads are pinned **1:1** to host CPUs 2 and 3; every other thread is confined to ''2-3'' | + | The branch ships a script that cross-checks the allocator' |
| <code bash> | <code bash> | ||
| - | cat /sys/ | + | GUEST_PASS=< |
| </ | </ | ||
| - | < | + | Override its lab defaults ('' |
| - | 2-3 | + | |
| - | </code> | + | |
| - | Expected on the isolated run of §4.3: the same shape with 4 and 5 (or 6 and 7) in place of 2 and 3, and the emulator threads confined to the housekeeping CPUs — **excluding** the isolated ones. That exclusion matters: '' | + | ---- |
| - | Inside | + | ===== Part 5 — Known limitations ===== |
| + | |||
| + | ==== 5.1 nohz_full and rcu_nocbs do nothing on the shipped kernel ==== | ||
| <code bash> | <code bash> | ||
| - | lscpu | grep -E 'CPU\(s\)|Thread\(s\) per core' | + | dmesg | grep -iE 'nohz|Unknown kernel command line' |
| + | (zcat / | ||
| </ | </ | ||
| - | A 2-vCPU whole-core-SMT workload sees '' | + | < |
| + | Housekeeping: nohz unsupported. Build with CONFIG_NO_HZ_FULL | ||
| + | Unknown kernel command line parameters "... rcu_nocbs=4,5,6,7 nohz_full=4, | ||
| + | # CONFIG_NO_HZ_FULL is not set | ||
| + | CONFIG_CPU_ISOLATION=y | ||
| + | </ | ||
| - | ==== 4.5 One-shot cross-check ==== | + | ^ Argument ^ Effect ^ |
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| - | The branch ships a script that cross-checks | + | So what you can demonstrate today is **scheduler isolation**: |
| - | <code bash> | + | ==== 5.2 EVE's own cpuset stays on CPU 0 ==== |
| - | GUEST_PASS=< | + | |
| - | </code> | + | '' |
| + | |||
| + | ==== 5.3 The vault reports a PCR mismatch on the first boot ==== | ||
| - | Override its lab defaults ('' | + | Changing the kernel command line changes PCRs 8, 9 and 14, so '' |
| ---- | ---- | ||
| - | ===== 5. Troubleshooting ===== | + | ===== Part 6 — Troubleshooting ===== |
| ^ Symptom ^ Cause ^ Fix ^ | ^ Symptom ^ Cause ^ Fix ^ | ||
| - | | ''/ | + | | Cannot find the property in the controller UI | it is not exposed there | set it via Terraform or REST (Step 6) | |
| - | | '' | + | | Property set in Terraform, node still shows '' |
| + | | Property set on the application instead of the node | '' | ||
| + | | ''/ | ||
| + | | '' | ||
| + | | **Pinned VM stays on the dedicated cores after enabling the switch** | a running workload holds its allocation; '' | ||
| + | | VM halted with '' | ||
| + | | '' | ||
| | '' | | '' | ||
| - | | Pinned workload placed on dedicated cores, never isolated | + | | Placement refused citing a synthetic topology |
| - | | Isolated cores show as free but nothing can use them | expected | + | | Isolated cores free but nothing can use them | expected |
| - | | Placement refused with a synthetic-topology error | sysfs topology discovery failed | check ''/ | + | | SSH host key changed after reboot |
| - | | Boot loop, '' | + | | Boot loop, '' |
| - | | '' | + | |
| ---- | ---- | ||
| - | ===== 6. Reference ===== | + | ===== Part 7 — Reference ===== |
| - | * '' | + | * '' |
| * '' | * '' | ||
| * Pool kinds and error codes: '' | * Pool kinds and error codes: '' | ||
| * Placement logic: '' | * Placement logic: '' | ||
| + | * The allocation-reuse shortcut discussed in Troubleshooting: | ||
eve-kvm/core-isolation.1789750033.txt.gz · Last modified: by mc
