<feed xmlns='http://www.w3.org/2005/Atom'>
<title>openslx-ng/ipxe.git/src/arch/x86/transitions, branch master</title>
<subtitle>Fork of ipxe; additional commands and features</subtitle>
<id>https://git.openslx.org/openslx-ng/ipxe.git/atom/src/arch/x86/transitions?h=master</id>
<link rel='self' href='https://git.openslx.org/openslx-ng/ipxe.git/atom/src/arch/x86/transitions?h=master'/>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/'/>
<updated>2018-03-21T15:00:53+00:00</updated>
<entry>
<title>[librm] Ensure that inline code symbols are unique</title>
<updated>2018-03-21T15:00:53+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2018-03-21T14:47:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=bc85368cdd311fe68ffcf251e7e8e90c14f8a9dc'/>
<id>urn:sha1:bc85368cdd311fe68ffcf251e7e8e90c14f8a9dc</id>
<content type='text'>
Commit 6149e0a ("[librm] Provide symbols for inline code placed into
other sections") may cause build failures due to duplicate label names
if the compiler chooses to duplicate inline assembly code.

Fix by using the "%=" special format string to include a
guaranteed-unique number within the label name.

The "%=" will be expanded only if constraints exist for the inline
assembly.  This fix therefore requires that all REAL_CODE() fragments
use a (possibly empty) constraint list.

Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Add facility to provide register and stack dump for CPU exceptions</title>
<updated>2018-03-18T12:59:34+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2018-03-18T12:54:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=89e31f8491895e6196d4ba56aee3809261aa6b89'/>
<id>urn:sha1:89e31f8491895e6196d4ba56aee3809261aa6b89</id>
<content type='text'>
When DEBUG=librm_mgmt is enabled, intercept CPU exceptions and provide
a register and stack dump, then drop to an emergency shell.  Exiting
from the shell will almost certainly not work, but this provides an
opportunity to view the register and stack dump and carry out some
basic debugging.

Note that we can intercept only the first 8 CPU exceptions, since a
PXE ROM is not permitted to rebase the PIC.

Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Fail gracefully if asked to ioremap() a zero length</title>
<updated>2017-03-21T12:17:18+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2017-03-21T12:17:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=d25e7daf47efbefa83bbf9c07e044cdf747c7fda'/>
<id>urn:sha1:d25e7daf47efbefa83bbf9c07e044cdf747c7fda</id>
<content type='text'>
Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Conditionalize the workaround for the Tivoli VMM's SSE garbling</title>
<updated>2016-11-08T17:37:59+00:00</updated>
<author>
<name>Laszlo Ersek</name>
</author>
<published>2016-10-26T22:13:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=dd9a14de35d2c4e308170ad2b51722d448d04e76'/>
<id>urn:sha1:dd9a14de35d2c4e308170ad2b51722d448d04e76</id>
<content type='text'>
Commit 71560d1 ("[librm] Preserve FPU, MMX and SSE state across calls
to virt_call()") added FXSAVE and FXRSTOR instructions to iPXE.  In
KVM virtual machines, these instructions execute fine as long as the
host CPU supports the "unrestricted_guest" feature (that is, it can
virtualize big real mode natively).  On older host CPUs however, KVM
has to emulate big real mode, and it currently doesn't implement
FXSAVE emulation.

Upstream QEMU rebuilt iPXE at commit 0418631 ("[thunderx] Fix
compilation with older versions of gcc") which is a descendant of
commit 71560d1 (see above).

This was done in QEMU commit ffdc5a2 ("ipxe: update submodule from
4e03af8ec to 041863191").  The resultant binaries were bundled with
the QEMU v2.7.0 release; see QEMU commit c52125a ("ipxe: update
prebuilt binaries").

This distributed the iPXE workaround for the Tivoli VMM bug to a
number of KVM users with old host CPUs, causing KVM emulation failures
(guest crashes) for them while netbooting.

Make the FXSAVE and FXRSTOR instructions conditional on a new feature
test macro called TIVOLI_VMM_WORKAROUND.  Define the macro by default.

There is prior art for an assembly file including config/general.h:
see arch/x86/prefix/romprefix.S.  Also, TIVOLI_VMM_WORKAROUND seems to
be a good fit for the "Obscure configuration options" section in
config/general.h.

Cc: Bandan Das &lt;bsd@redhat.com&gt;
Cc: Gerd Hoffmann &lt;kraxel@redhat.com&gt;
Cc: Greg &lt;rollenwiese@yahoo.com&gt;
Cc: Michael Brown &lt;mcb30@ipxe.org&gt;
Cc: Michael Prokop &lt;launchpad@michael-prokop.at&gt;
Cc: Paolo Bonzini &lt;pbonzini@redhat.com&gt;
Cc: Peter Pickford &lt;arch@netremedies.ca&gt;
Cc: Radim Krčmář &lt;rkrcmar@redhat.com&gt;
Ref: https://bugs.archlinux.org/task/50778
Ref: https://bugs.launchpad.net/qemu/+bug/1623276
Ref: https://bugzilla.proxmox.com/show_bug.cgi?id=1182
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1356762
Signed-off-by: Laszlo Ersek &lt;lersek@redhat.com&gt;
Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Preserve FPU, MMX and SSE state across calls to virt_call()</title>
<updated>2016-05-02T13:02:31+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2016-04-27T10:03:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=71560d185475117b10994d839afe059577e7768c'/>
<id>urn:sha1:71560d185475117b10994d839afe059577e7768c</id>
<content type='text'>
The IBM Tivoli Provisioning Manager for OS Deployment (also known as
TPMfOSD, Rembo-ia32, or Rembo Auto-Deploy) has a serious bug in some
older versions (observed with v5.1.1.0, apparently fixed by v7.1.1.0)
which can lead to arbitrary data corruption.

As mentioned in commit 87723a0 ("[libflat] Test A20 gate without
switching to flat real mode"), Tivoli's NBP sets up a VMM and makes
calls to the PXE stack in VM86 mode.  This appears to be some kind of
attempt to run PXE API calls inside a sandbox.  The VMM is fairly
sophisticated: for example, it handles our attempts to switch into
protected mode and patches our GDT so that our protected-mode code
runs in ring 1 instead of ring 0.  However, it neglects to apply any
memory protections.  In particular, it does not enable paging and
leaves us with 4GB segment limits.  We can therefore trivially break
out of the sandbox by simply overwriting the GDT (or by modifying any
of Tivoli's VMM code or data structures).

When we attempt to execute privileged instructions (such as "lidt"),
the CPU raises an exception and control is passed to the Tivoli VMM.
This may result in a call to Tivoli's memcpy() function.

Tivoli's memcpy() function includes optimisations which use the SSE
registers %xmm0-%xmm3 to speed up aligned memory copies.

Unfortunately, the Tivoli VMM's exception handler does not save or
restore %xmm0-%xmm3.  The net effect of this bug in the Tivoli VMM is
that any privileged instruction (such as "lidt") issued by iPXE may
result in unexpected corruption of the %xmm0-%xmm3 registers.

Even more unfortunately, this problem affects the code path taken in
response to a hardware interrupt from the NIC, since that code path
will call PXENV_UNDI_ISR.  The net effect therefore becomes that any
NIC hardware interrupt (e.g. due to a received packet) may result in
unexpected corruption of the %xmm0-%xmm3 registers.

If a packet arrives while Tivoli is in the middle of using its
memcpy() function, then the unexpected corruption of the %xmm0-%xmm3
registers will result in unexpected corruption in the destination
buffer.  The net effect therefore becomes that any received packet may
result in a 16-byte block of corruption somewhere in any data that
Tivoli copied using its memcpy() function.

We can work around this bug in the Tivoli VMM by saving and restoring
the %xmm0-%xmm3 registers across calls to virt_call().  To work around
the problem, we need to save registers before attempting to execute
any privileged instructions, and ensure that we attempt no further
privileged instructions after restoring the registers.

This is less simple than it may sound.  We can use the "movups"
instruction to save and restore individual registers, but this will
itself generate an undefined opcode exception if SSE is not currently
enabled according to the flags in %cr0 and %cr4.  We can't access %cr0
or %cr4 before attempting the "movups" instruction, because access a
control register is itself a privileged instruction (which may
therefore trigger corruption of the registers that we're trying to
save).

The best solution seems to be to use the "fxsave" and "fxrstor"
instructions.  If SSE is not enabled, then these instructions may fail
to save and restore the SSE register contents, but will not generate
an undefined opcode exception.  (If SSE is not enabled, then we don't
really care about preserving the SSE register contents anyway.)

The use of "fxsave" and "fxrstor" introduces an implicit assumption
that the CPU supports SSE instructions (even though we make no
assumption about whether or not SSE is currently enabled).  SSE was
introduced in 1999 with the Pentium III (and added by AMD in 2001),
and is an architectural requirement for x86_64.  Experimentation with
current versions of gcc suggest that it may generate SSE instructions
even when using "-m32", unless an explicit "-march=i386" or "-mno-sse"
is used to inhibit this.  It therefore seems reasonable to assume that
SSE will be supported on any hardware that might realistically be used
with new iPXE builds.

As a side benefit of this change, the MMX register %mm0 will now be
preserved across virt_call() even in an i386 build of iPXE using a
driver that requires readq()/writeq(), and the SSE registers
%xmm0-%xmm5 will now be preserved across virt_call() even in an x86_64
build of iPXE using the Hyper-V netvsc driver.

Experimentation suggests that this change adds around 10% to the
number of cycles required for a do-nothing virt_call(), most of which
are due to the extra bytes copied using "rep movsb".  Since the number
of bytes copied is a compile-time constant local to librm.S, we could
potentially reduce this impact by ensuring that we always copy a whole
number of dwords and so can use "rep movsl" instead of "rep movsb".

Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Reduce real-mode stack consumption in virt_call()</title>
<updated>2016-04-29T10:48:39+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2016-04-29T10:33:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=2d42d3cff6e941c4e04d15dc29ea670f2fdb7b0c'/>
<id>urn:sha1:2d42d3cff6e941c4e04d15dc29ea670f2fdb7b0c</id>
<content type='text'>
Some PXE NBPs are known to make PXE API calls with very little space
available on the real-mode stack.  For example, the Rembo-ia32 NBP
from some versions of IBM's Tivoli Provisioning Manager for Operating
System Deployment (TPMfOSD) will issue calls with the real-mode stack
placed at 0000:03d2; this is at the end of the interrupt vector table
and leaves only 498 bytes of stack space available before overwriting
the hardware IRQ vectors.  This limits the amount of state that we can
preserve before transitioning to protected mode.

Work around these challenging conditions by preserving everything
other than the initial register dump in a temporary static buffer
within our real-mode data segment, and copying the contents of this
buffer to the protected-mode stack.

Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[comboot] Support COMBOOT in 64-bit builds</title>
<updated>2016-04-15T14:31:36+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2016-04-14T15:48:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=5e5450c2d04e6f976ea4cef5db50e136d4a06282'/>
<id>urn:sha1:5e5450c2d04e6f976ea4cef5db50e136d4a06282</id>
<content type='text'>
Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Do not unconditionally preserve flags across virt_call()</title>
<updated>2016-03-12T12:39:17+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2016-03-12T12:39:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=cc9f31ee0cfd4ef9cf05ef0621fc933814489b3d'/>
<id>urn:sha1:cc9f31ee0cfd4ef9cf05ef0621fc933814489b3d</id>
<content type='text'>
Commit 196f0f2 ("[librm] Convert prot_call() to a real-mode near
call") introduced a regression in which any deliberate modification to
the low 16 bits of the CPU flags (in struct i386_all_regs) would be
overwritten with the original flags value at the time of entry to
prot_call().

The regression arose because the alignment requirements of the
protected-mode stack necessitated the insertion of two bytes of
padding immediately below the prot_call() return address.  The
solution chosen was to extend the existing "pushfl / popfl" pair to
"pushfw;pushfl / popfl;popfw".  The extra "pushfw / popfw" appears at
first glance to be a no-op, but fails to take into account the fact
that the flags restored by popfl may have been deliberately modified
by the protected-mode function.

Fix by replacing "pushfw / popfw" with "pushw %ss / popw %ss".  While
%ss does appear within struct i386_all_regs, any modification to the
stored value has always been ignored by prot_call() anyway.

The most visible symptom of this regression was that SAN booting would
fail since every INT 13 call would be chained to the original INT 13
vector.

Reported-by: Vishvananda Ishaya &lt;vishvananda@gmail.com&gt;
Reported-by: Jamie Thompson &lt;forum.ipxe@jamie-thompson.co.uk&gt;
Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Support ioremap() for addresses above 4GB in a 64-bit build</title>
<updated>2016-02-26T15:34:28+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2016-02-26T15:34:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=99b5216b1c71dba22dab734e0945887525493cde'/>
<id>urn:sha1:99b5216b1c71dba22dab734e0945887525493cde</id>
<content type='text'>
Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
<entry>
<title>[librm] Add support for running in 64-bit long mode</title>
<updated>2016-02-24T03:10:12+00:00</updated>
<author>
<name>Michael Brown</name>
</author>
<published>2016-02-18T02:44:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.openslx.org/openslx-ng/ipxe.git/commit/?id=614305743031bdfc02cb4ce346e450cd1d476e17'/>
<id>urn:sha1:614305743031bdfc02cb4ce346e450cd1d476e17</id>
<content type='text'>
Add support for running the BIOS version of iPXE in 64-bit long mode.
A 64-bit BIOS version of iPXE can be built using e.g.

  make bin-x86_64-pcbios/ipxe.usb
  make bin-x86_64-pcbios/8086100e.mrom

The 64-bit BIOS version should appear to function identically to the
normal 32-bit BIOS version.  The physical memory layout is unaltered:
iPXE is still relocated to the top of the available 32-bit address
space.  The code is linked to a virtual address of 0xffffffffeb000000
(in the negative 2GB as required by -mcmodel=kernel), with 4kB pages
created to cover the whole of .textdata.  2MB pages are created to
cover the whole of the 32-bit address space.

The 32-bit portions of the code run with VIRTUAL_CS and VIRTUAL_DS
configured such that truncating a 64-bit virtual address gives a
32-bit virtual address pointing to the same physical location.

The stack pointer remains as a physical address when running in long
mode (although the .stack section is accessible via the negative 2GB
virtual address); this is done in order to simplify the handling of
interrupts occurring while executing a portion of 32-bit code with
flat physical addressing via PHYS_CODE().

Interrupts may be enabled in either 64-bit long mode, 32-bit protected
mode with virtual addresses, 32-bit protected mode with physical
addresses, or 16-bit real mode.  Interrupts occurring in any mode
other than real mode will be reflected down to real mode and handled
by whichever ISR is hooked into the BIOS interrupt vector table.

Signed-off-by: Michael Brown &lt;mcb30@ipxe.org&gt;
</content>
</entry>
</feed>
