oxidecomputer / oxidecomputer/propolis

Support PAM registers in i440fx

Open
#523 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
270
Forks
42
Avg merge
4d 5h
Merged PRs (30d)
6

Description

I spent the afternoon debugging why a SeaBIOS ROM was wholly unable to boot under propolis. With its debugging configuration set to maximum, the ROM would not make any forward progress before falling into a loop of unhandled IO port accesses to a seemingly nonsensical address:

 Sep 11 21:47:19.977 ERRO Unhandled pio In(IoPort { port: 0, bytes: 2 }), rip: 0
 Sep 11 21:47:19.980 ERRO Unhandled pio In(IoPort { port: 83, bytes: 2 }), rip: 51913
 Sep 11 21:47:20.055 ERRO Unhandled pio In(IoPort { port: 600, bytes: 2 }), rip: 31545
 Sep 11 21:47:20.055 ERRO Unhandled pio Out(IoPort { port: 600, bytes: 1 }, ff), rip: 31533
 Sep 11 21:47:20.056 ERRO Unhandled pio In(IoPort { port: 600, bytes: 2 }), rip: 31517
 Sep 11 21:47:20.056 ERRO Unhandled pio Out(IoPort { port: 600, bytes: 1 }, ff), rip: 31521
 Sep 11 21:47:20.056 ERRO Unhandled pio Out(IoPort { port: 600, bytes: 1 }, ff), rip: 31527
 Sep 11 21:47:20.056 ERRO Unhandled pio In(IoPort { port: 600, bytes: 2 }), rip: 31517

After reading through the seabios source, I traced IO port accesses in the kernel vmm, since in theory the ROM should be accessing the CMOS (RTC) to determine if the boot was a resume or "full POST". No such access occurred, which suggested that we weren't even progressing to the early POST logic. After further reading, and single-stepping a guest during boot on an Intel machine, I came to scrutinize the literal first instruction of the ROM:

reset_vector:
        ljmpw $SEG_BIOS, $entry_post

... and ...

#define SEG_BIOS     0xf000

This long-jmp would result in a %cs base address of 0xf0000 to use when offsetting the entry_post address. This is a bit odd, considering the ROM is mapped at 0xfffe0000 (offset for size) in order to locate the first instruction at the ISA-defined 0xfffffff0 address.

Recalling that i440fx (and some subsequent Intel chipsets like Q35) have some special remapping behavior using their "PAM" registers. Said registers can cause ranges such as 0xf0000 to alias to the ROM. I suspect we'll need to at least partially emulate such behavior in order to run SeaBIOS without significant modification.

What I believe this requires from bhyve and propolis:

  1. Supporting more than the low (currently 8) number of memory mappings in the guest address space
  2. Better handling of VM_EXITCODE_PAGING conditions, where a present mapping in the guest address space fails protection checks. Falling back to instruction-emulation logic for this, and eschewing the PAGING exitcode entirely would probably be proper
  3. Wiring up propolis to juggle the aliased mappings when the guest twiddles the PAM registers in the chipset

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the bhyve kernel VMM handling of guest memory mappings and VM_EXITCODE_PAGING, then inspect how propolis wires chipset register accesses into the guest address space. The issue identifies PAM registers, aliased mappings, and protection-failure fallback as the required areas. Done means SeaBIOS can boot on i440fx with PAM-controlled ROM aliases and the required mapping limits are supported.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.