open-power / skiboot

OPAL boot and runtime firmware for POWER
Apache License 2.0
100 stars 134 forks source link

skiboot and HRMOR #239

Closed asurati closed 5 years ago

asurati commented 5 years ago

PowerISA 3.0b section 5.7.3.1 (Hypervisor Offset Real Mode Address) and its programming note seem to suggest that HRMOR acts as a base address, and the EA acts as the offset within the implementation-defined chunk (which can be of max size 64MB) that begins at that base address.

Thus, if HRMOR is set to 0, and if the implementation of the CPU sets the chunk size to 64MB, skiboot should not be able to access anything outside of [0, 64MB) range while it is running under the hypervisor real address mode without changing the HRMOR.

A note inside the function per_thread_sanity_checks says that skiboot can't work with nonzero HRMOR.

So, how is it able to relocate itself to SKIBOOT_BASE = 0x30000000 without juggling with HRMOR values? Clearly, skiboot works on real hardware (unfortunately, I don't have access to one), so am I misinterpreting the ISA?

mikey commented 5 years ago

Thus, if HRMOR is set to 0, and if the implementation of the CPU sets the chunk size to 64MB, skiboot should not be able to access anything outside of [0, 64MB) range while it is running under the hypervisor real address mode without changing the HRMOR.

HRMOR doesn't limit access like that. It just offsets where real mode accesses are.

npiggin commented 5 years ago

skiboot does not use HRMOR!=0 anyway.

asm/head.S boot_entry copies the skiboot image to SKIBOOT_BASE and then jumps to the new location.

oohal commented 5 years ago

PowerISA 3.0b section 5.7.3.1 (Hypervisor Offset Real Mode Address) and its programming note seem to suggest that HRMOR acts as a base address, and the EA acts as the offset within the implementation-defined chunk (which can be of max size 64MB) that begins at that base address.

Thus, if HRMOR is set to 0, and if the implementation of the CPU sets the chunk size to 64MB, skiboot should not be able to access anything outside of [0, 64MB) range while it is running under the hypervisor real address mode without changing the HRMOR.

As mikey said, you're mis-interpreting how HRMOR works. The current HRMOR value is ORed into the address of any load/store operations generated by that core so when set to 64MB you wouldn't be able to access from [0..64MB). My interpretation of the "chunk size" is that it's the CPU's minimum supported alignment for HRMOR values, so if a CPU had a chunk size of 64MB then HRMOR would need to be set to 64MB, 128MB, etc.

That all said, have a read of Sec 5.7.3 Hypervisor Real And Virtual Real Addressing Modes. When EA_0 (the high bit) is set HRMOR is bypassed completely so it's not very useful as a security feature. IIRC it exists mainly to support our large multi-chassis systems. Each chassis boots as an independent node before being merged into a single address space. When the nodes are merged they go from all having their local memory at zero to some random offset and HRMOR is a neat hack to paper over that until firmware is ready to deal with it.

A note inside the function per_thread_sanity_checks says that skiboot can't work with nonzero HRMOR.

So, how is it able to relocate itself to SKIBOOT_BASE = 0x30000000 without juggling with HRMOR values? Clearly, skiboot works on real hardware (unfortunately, I don't have access to one), so am I misinterpreting the ISA?

As a part of the ABI between hostboot and skiboot we require the HRMOR to be set to zero before entering skiboot. I did write some code a long time ago to have skiboot fix the HRMOR inside of boot_entry to work around a hostboot bug, but hostboot fixed the bug before I found a robust way to handle it. Changing HRMOR is a little tricky since you need to ensure that each thread in a core has the same value and synchronising between threads before we've setup any of skiboot's runtime environment is a bit of a headache, but it is possible to do.

asurati commented 5 years ago

Thank you for the comments.

The (incorrect) idea about HRMOR restricting the accesses appeared in my mind after reading the following programming note:

EA(4:63-r) should equal (60-r)0. If this condition is satisfied, ORing the effective address with the offset produces a result that is equivalent to adding the effective address and the offset.

If the addresses are kept as suggested by the note, the resultant addresses remain bounded within the interval [hrmor, hrmor + chunk_size), rolling over at the edges.

It seems that the description of the behaviour (as printed in the ISA) is tighter than its implementation on the machines.