Hi,
http://www.seabios.org/pipermail/seabios/2010-March/000396.html
Could anyone explain what the difficulty with OHCI bulk in 16-bit mode is before I spend a few hours discovering for myself?
Jonathan Kollasch
On Tue, Sep 21, 2010 at 07:51:37PM +0000, Jonathan A. Kollasch wrote:
Hi,
http://www.seabios.org/pipermail/seabios/2010-March/000396.html
Could anyone explain what the difficulty with OHCI bulk in 16-bit mode is before I spend a few hours discovering for myself?
In order to start a bulk or control transmission on ohci, one must write to the cmdstatus register. You'll see this in the code as:
writel(&cntl->regs->cmdstatus, OHCI_CLF);
This register is a memory mapped register in one of the PCI bars.
When in 16bit mode, one can only reliably access the first 1Meg of ram. Unfortunately, the PCI bar is going to be in high memory.
I couldn't think of any reliable way to toggle the cmdstatus bit to start a bulk transfer while in 16bit mode. I thought of a few different hacks - but they all seemed to fragile.
-Kevin
Kevin O'Connor wrote:
When in 16bit mode, one can only reliably access the first 1Meg of ram.
Flat real mode?
//Peter
On Wed, Sep 22, 2010 at 06:40:58AM +0200, Peter Stuge wrote:
Kevin O'Connor wrote:
When in 16bit mode, one can only reliably access the first 1Meg of ram.
Flat real mode?
The BIOS can put the machine in big real mode when it launches the OS, but it can't expect that it will always be called in big real mode. The BIOS could attempt to transition to 32bit mode (or big real mode) in the disk handler, but it may have been called in vm86 mode which would then effectively cause a crash. (It also wipes out the hidden segment registers which may confuse the OS.) Use of vm86 mode is not uncommon - freedos does it and so does (I'm told) Linux.
-Kevin
On 09/22/2010 05:52 AM, Kevin O'Connor wrote:
On Wed, Sep 22, 2010 at 06:40:58AM +0200, Peter Stuge wrote:
Kevin O'Connor wrote:
When in 16bit mode, one can only reliably access the first 1Meg of ram.
Flat real mode?
The BIOS can put the machine in big real mode when it launches the OS, but it can't expect that it will always be called in big real mode. The BIOS could attempt to transition to 32bit mode (or big real mode) in the disk handler, but it may have been called in vm86 mode which would then effectively cause a crash. (It also wipes out the hidden segment registers which may confuse the OS.) Use of vm86 mode is not uncommon - freedos does it and so does (I'm told) Linux.
The standard way to deal with this in the BIOS (and *only* the BIOS can do this!) is to trap into SMM and have an SMI handler do the I/O. Taking an SMI drops the CPU into big real mode regardless of what the previous CPU mode was.
-hpa
On 09/22/2010 11:21 AM, H. Peter Anvin wrote:
On 09/22/2010 05:52 AM, Kevin O'Connor wrote:
On Wed, Sep 22, 2010 at 06:40:58AM +0200, Peter Stuge wrote:
Kevin O'Connor wrote:
When in 16bit mode, one can only reliably access the first 1Meg of ram.
Flat real mode?
The BIOS can put the machine in big real mode when it launches the OS, but it can't expect that it will always be called in big real mode. The BIOS could attempt to transition to 32bit mode (or big real mode) in the disk handler, but it may have been called in vm86 mode which would then effectively cause a crash. (It also wipes out the hidden segment registers which may confuse the OS.) Use of vm86 mode is not uncommon - freedos does it and so does (I'm told) Linux.
The standard way to deal with this in the BIOS (and *only* the BIOS can do this!) is to trap into SMM and have an SMI handler do the I/O. Taking an SMI drops the CPU into big real mode regardless of what the previous CPU mode was.
The other option is to enter protected mode for the operation, or, if you detect that you're already in protected mode (which means V86 mode) then you invoke the INT 15h mover. Not all environments is going to handle the INT 15h mover correctly, though.
-hpa
On Wed, Sep 22, 2010 at 01:08:07PM -0700, H. Peter Anvin wrote:
On 09/22/2010 11:21 AM, H. Peter Anvin wrote:
On 09/22/2010 05:52 AM, Kevin O'Connor wrote:
The BIOS can put the machine in big real mode when it launches the OS, but it can't expect that it will always be called in big real mode. The BIOS could attempt to transition to 32bit mode (or big real mode) in the disk handler, but it may have been called in vm86 mode which would then effectively cause a crash. (It also wipes out the hidden segment registers which may confuse the OS.) Use of vm86 mode is not uncommon - freedos does it and so does (I'm told) Linux.
The standard way to deal with this in the BIOS (and *only* the BIOS can do this!) is to trap into SMM and have an SMI handler do the I/O. Taking an SMI drops the CPU into big real mode regardless of what the previous CPU mode was.
Using SMI is something I've thought a little about. It does have some snags: SMI programming is chipset specific on real hardware so one can't deploy a single solution for all coreboot users; kvm doesn't have SMI support; using an SMI to get out of vm86 mode requires the BIOS to emulate all memory accesses to user memory (manually walking the page table, forcing page faults) which is tricky; there might be subtle security implications with having a BIOS interface that can effectively escalate privileges.
The other option is to enter protected mode for the operation, or, if you detect that you're already in protected mode (which means V86 mode)
I didn't think there was a way for the user code to know it was running in vm86 mode - I thought it appeared just like regular real-mode. One could try to go into protected mode and try to catch the failure, but I'd guess most OSs that run code in vm86 mode would trap and abort in that situation.
then you invoke the INT 15h mover. Not all environments is going to handle the INT 15h mover correctly, though.
Are you referring to INT 0x15 ah=0x89? This can request a transition to protected mode, but I didn't see any equivalent way to get back to real mode.
A related call is INT 0x15 ah=0x87 which does a highmem capable memcpy. Unfortunately this handler does a 16bit memcpy (rep movsw), and the OHCI spec requires the cmdstatus register be accessed with a 32bit memory access.
-Kevin
On 09/22/2010 06:16 PM, Kevin O'Connor wrote:
Using SMI is something I've thought a little about. It does have some snags: SMI programming is chipset specific on real hardware so one can't deploy a single solution for all coreboot users; kvm doesn't have SMI support;
Right so far, althoguh SMI is pretty easy to implement.
using an SMI to get out of vm86 mode requires the BIOS to emulate all memory accesses to user memory (manually walking the page table, forcing page faults) which is tricky;
Actually you can switch to protected mode and turn the page tables on if you want.
there might be subtle security implications with having a BIOS interface that can effectively escalate privileges.
Yes.
The other option is to enter protected mode for the operation, or, if you detect that you're already in protected mode (which means V86 mode)
I didn't think there was a way for the user code to know it was running in vm86 mode - I thought it appeared just like regular real-mode. One could try to go into protected mode and try to catch the failure, but I'd guess most OSs that run code in vm86 mode would trap and abort in that situation.
No, the SMSW instruction can be used to distinguish protected mode and therefore V86 mode.
then you invoke the INT 15h mover. Not all environments is going to handle the INT 15h mover correctly, though.
Are you referring to INT 0x15 ah=0x89? This can request a transition to protected mode, but I didn't see any equivalent way to get back to real mode.
No, AH=0x87.
A related call is INT 0x15 ah=0x87 which does a highmem capable memcpy. Unfortunately this handler does a 16bit memcpy (rep movsw), and the OHCI spec requires the cmdstatus register be accessed with a 32bit memory access.
That might be a problem if that is actually done that way (which it generally won't.) Still, you do have the issue of what happens in a V86 environment if it doesn't just pass code to the original BIOS.
-hpa
On Wed, Sep 22, 2010 at 06:33:46PM -0700, H. Peter Anvin wrote:
On 09/22/2010 06:16 PM, Kevin O'Connor wrote:
using an SMI to get out of vm86 mode requires the BIOS to emulate all memory accesses to user memory (manually walking the page table, forcing page faults) which is tricky;
Actually you can switch to protected mode and turn the page tables on if you want.
That's a good idea. Though it still sounds tricky to handle page faults.
I didn't think there was a way for the user code to know it was running in vm86 mode - I thought it appeared just like regular real-mode. One could try to go into protected mode and try to catch the failure, but I'd guess most OSs that run code in vm86 mode would trap and abort in that situation.
No, the SMSW instruction can be used to distinguish protected mode and therefore V86 mode.
Thanks. Do you know of a way to backup the hidden segment registers? The BIOS can be invoked in real mode or bigreal mode. I didn't see a way for the BIOS to determine this so that it can properly return in the same mode (real vs bigreal).
A related call is INT 0x15 ah=0x87 which does a highmem capable memcpy. Unfortunately this handler does a 16bit memcpy (rep movsw), and the OHCI spec requires the cmdstatus register be accessed with a 32bit memory access.
That might be a problem if that is actually done that way (which it generally won't.) Still, you do have the issue of what happens in a V86 environment if it doesn't just pass code to the original BIOS.
-Kevin
On 09/22/2010 07:05 PM, Kevin O'Connor wrote:
Actually you can switch to protected mode and turn the page tables on if you want.
That's a good idea. Though it still sounds tricky to handle page faults.
Yes, probably. On the other hand, if the BIOS low-level hardware drivers are executed in V86 mode without a 1:1 mapping you're pretty much dead anyway (since DMA would be all wrong.)
I didn't think there was a way for the user code to know it was running in vm86 mode - I thought it appeared just like regular real-mode. One could try to go into protected mode and try to catch the failure, but I'd guess most OSs that run code in vm86 mode would trap and abort in that situation.
No, the SMSW instruction can be used to distinguish protected mode and therefore V86 mode.
Thanks. Do you know of a way to backup the hidden segment registers? The BIOS can be invoked in real mode or bigreal mode. I didn't see a way for the BIOS to determine this so that it can properly return in the same mode (real vs bigreal).
There isn't one (other than binary search of the faulting space) except SMM.
-hpa
On Wed, Sep 22, 2010 at 08:09:06PM -0700, H. Peter Anvin wrote:
On 09/22/2010 07:05 PM, Kevin O'Connor wrote:
Actually you can switch to protected mode and turn the page tables on if you want.
That's a good idea. Though it still sounds tricky to handle page faults.
Yes, probably. On the other hand, if the BIOS low-level hardware drivers are executed in V86 mode without a 1:1 mapping you're pretty much dead anyway (since DMA would be all wrong.)
I was thinking in terms of a general SMI handler that could be used to replace all 16bit code.
I suppose one could write a simple SMI handler that just set the OHCI cmdstatus bits. That probably wouldn't be too hard and it wouldn't be too complex.
I didn't think there was a way for the user code to know it was running in vm86 mode - I thought it appeared just like regular real-mode. One could try to go into protected mode and try to catch the failure, but I'd guess most OSs that run code in vm86 mode would trap and abort in that situation.
No, the SMSW instruction can be used to distinguish protected mode and therefore V86 mode.
Thanks. Do you know of a way to backup the hidden segment registers? The BIOS can be invoked in real mode or bigreal mode. I didn't see a way for the BIOS to determine this so that it can properly return in the same mode (real vs bigreal).
There isn't one (other than binary search of the faulting space) except SMM.
I think that pretty much only leaves SMM then.
-Kevin
On 09/23/2010 05:56 AM, Kevin O'Connor wrote:
I was thinking in terms of a general SMI handler that could be used to replace all 16bit code.
I suppose one could write a simple SMI handler that just set the OHCI cmdstatus bits. That probably wouldn't be too hard and it wouldn't be too complex.
Well, if you write a "all SMI BIOS" then you presumably would have entry/exit code and would be able to amortize the larger amount of work across a bigger code base.
-hpa
On 09/23/10 14:56, Kevin O'Connor wrote:
I suppose one could write a simple SMI handler that just set the OHCI cmdstatus bits. That probably wouldn't be too hard and it wouldn't be too complex.
Hi folks,
What is the current state of affairs? Sooner or later we'll need a solution for the pci-bar-access-from-real-mode issue ...
I looked briefly at the usb3 specs and I think it is impossible to drive a xHCI adapter without access to the PCI bar.
Also AHCI support needs access to the PCI bar to submit commands and check status.
cheers, Gerd
On 11/19/2010 02:58 PM, Gerd Hoffmann wrote:
On 09/23/10 14:56, Kevin O'Connor wrote:
I suppose one could write a simple SMI handler that just set the OHCI cmdstatus bits. That probably wouldn't be too hard and it wouldn't be too complex.
Hi folks,
What is the current state of affairs? Sooner or later we'll need a solution for the pci-bar-access-from-real-mode issue ...
I looked briefly at the usb3 specs and I think it is impossible to drive a xHCI adapter without access to the PCI bar.
Also AHCI support needs access to the PCI bar to submit commands and check status.
Would INT 15h, AH=87h do the job well enough? Otherwise it's probably SMM or bust...
-hpa
On Fri, Nov 19, 2010 at 03:39:58PM -0800, H. Peter Anvin wrote:
On 11/19/2010 02:58 PM, Gerd Hoffmann wrote:
On 09/23/10 14:56, Kevin O'Connor wrote:
I suppose one could write a simple SMI handler that just set the OHCI cmdstatus bits. That probably wouldn't be too hard and it wouldn't be too complex.
Hi folks,
What is the current state of affairs? Sooner or later we'll need a solution for the pci-bar-access-from-real-mode issue ...
I looked briefly at the usb3 specs and I think it is impossible to drive a xHCI adapter without access to the PCI bar.
Looking briefly myself, it does look like accessing the doorbell registers will be necessary.
Also AHCI support needs access to the PCI bar to submit commands and check status.
Yeah - it looks that way to me as well.
Would INT 15h, AH=87h do the job well enough? Otherwise it's probably SMM or bust...
I don't think int1587 would work reliably. So, I'd say SMM would be needed.
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode. The BIOS handler could then do its work and manually return the CPU to its initial state before returning to the guest. The BIOS would need to ensure that it didn't allow interrupts (or NMIs) while in this mode, but that's possible. One would probably want to ensure that the BIOS didn't touch any non-BIOS owned memory in this state as well, but that's also possible.
-Kevin
On 11/20/2010 12:50 PM, Kevin O'Connor wrote:
On Fri, Nov 19, 2010 at 03:39:58PM -0800, H. Peter Anvin wrote:
On 11/19/2010 02:58 PM, Gerd Hoffmann wrote:
On 09/23/10 14:56, Kevin O'Connor wrote:
I suppose one could write a simple SMI handler that just set the OHCI cmdstatus bits. That probably wouldn't be too hard and it wouldn't be too complex.
Hi folks,
What is the current state of affairs? Sooner or later we'll need a solution for the pci-bar-access-from-real-mode issue ...
I looked briefly at the usb3 specs and I think it is impossible to drive a xHCI adapter without access to the PCI bar.
Looking briefly myself, it does look like accessing the doorbell registers will be necessary.
Also AHCI support needs access to the PCI bar to submit commands and check status.
Yeah - it looks that way to me as well.
Would INT 15h, AH=87h do the job well enough? Otherwise it's probably SMM or bust...
I don't think int1587 would work reliably. So, I'd say SMM would be needed.
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode. The BIOS handler could then do its work and manually return the CPU to its initial state before returning to the guest. The BIOS would need to ensure that it didn't allow interrupts (or NMIs) while in this mode, but that's possible. One would probably want to ensure that the BIOS didn't touch any non-BIOS owned memory in this state as well, but that's also possible.
FWIW, I am currently working on a gateway for calling 32 bit functions in the relocated 32bit code from 16 bit code, opening up that are for more than the init functions. It works fine from what I can see also considering the mixture of register and stack passing of arguments. Would that be helpful here?
Stefan
-Kevin
SeaBIOS mailing list SeaBIOS@seabios.org http://www.seabios.org/mailman/listinfo/seabios
On Sat, Nov 20, 2010 at 12:58:56PM -0500, Stefan Berger wrote:
On 11/20/2010 12:50 PM, Kevin O'Connor wrote:
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode. The BIOS handler could then do its work and manually return the CPU to its initial state before returning to the guest. The BIOS would need to ensure that it didn't allow interrupts (or NMIs) while in this mode, but that's possible. One would probably want to ensure that the BIOS didn't touch any non-BIOS owned memory in this state as well, but that's also possible.
FWIW, I am currently working on a gateway for calling 32 bit functions in the relocated 32bit code from 16 bit code, opening up that are for more than the init functions. It works fine from what I can see also considering the mixture of register and stack passing of arguments. Would that be helpful here?
Is it something like stacks.c:call32() or is it via SMM?
BTW, are you reserving the relocated code or are you only doing this during the init phase?
-Kevin
On 11/20/2010 01:05 PM, Kevin O'Connor wrote:
On Sat, Nov 20, 2010 at 12:58:56PM -0500, Stefan Berger wrote:
On 11/20/2010 12:50 PM, Kevin O'Connor wrote:
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode. The BIOS handler could then do its work and manually return the CPU to its initial state before returning to the guest. The BIOS would need to ensure that it didn't allow interrupts (or NMIs) while in this mode, but that's possible. One would probably want to ensure that the BIOS didn't touch any non-BIOS owned memory in this state as well, but that's also possible.
FWIW, I am currently working on a gateway for calling 32 bit functions in the relocated 32bit code from 16 bit code, opening up that are for more than the init functions. It works fine from what I can see also considering the mixture of register and stack passing of arguments. Would that be helpful here?
Is it something like stacks.c:call32() or is it via SMM?
The way it works is that there is a jumptable with entries to the function in the 'high bios'. That jumptable along with all the other 32 bit code gets relocated to upper memory and in the 'lower BIOS' I keep a pointer to the jumptable in the 'high bios' for the upcall code to see. It's basically similar to what I have previously contributed to Bochs BIOS in Xen, just that the upcall code can deal with parameter passed via registers or a limited number on the stack.
http://xenbits.xensource.com/xen-4.0-testing.hg?file/e9156d9d996b/tools/firm...
BTW, are you reserving the relocated code or are you only doing this during the init phase?
The 'high bios' functions should be accessible all the time basically. So, the relocated code needs to be marked as e820-reserved memory -- I suppose that should do the trick then?
Stefan
-Kevin
On Sat, Nov 20, 2010 at 01:18:18PM -0500, Stefan Berger wrote:
On 11/20/2010 01:05 PM, Kevin O'Connor wrote:
Is it something like stacks.c:call32() or is it via SMM?
The way it works is that there is a jumptable with entries to the function in the 'high bios'. That jumptable along with all the other 32 bit code gets relocated to upper memory and in the 'lower BIOS' I keep a pointer to the jumptable in the 'high bios' for the upcall code to see. It's basically similar to what I have previously contributed to Bochs BIOS in Xen, just that the upcall code can deal with parameter passed via registers or a limited number on the stack.
http://xenbits.xensource.com/xen-4.0-testing.hg?file/e9156d9d996b/tools/firm...
That looks to be doing the same thing that stacks.c:call32() does.
BTW, are you reserving the relocated code or are you only doing this during the init phase?
The 'high bios' functions should be accessible all the time basically. So, the relocated code needs to be marked as e820-reserved memory -- I suppose that should do the trick then?
Yes, but of course that means the OS can't use the memory then. Why does the code need to be in high memory - why not just have it in the f-segment?
-Kevin
On 11/20/2010 01:28 PM, Kevin O'Connor wrote:
On Sat, Nov 20, 2010 at 01:18:18PM -0500, Stefan Berger wrote:
On 11/20/2010 01:05 PM, Kevin O'Connor wrote:
Is it something like stacks.c:call32() or is it via SMM?
The way it works is that there is a jumptable with entries to the function in the 'high bios'. That jumptable along with all the other 32 bit code gets relocated to upper memory and in the 'lower BIOS' I keep a pointer to the jumptable in the 'high bios' for the upcall code to see. It's basically similar to what I have previously contributed to Bochs BIOS in Xen, just that the upcall code can deal with parameter passed via registers or a limited number on the stack.
http://xenbits.xensource.com/xen-4.0-testing.hg?file/e9156d9d996b/tools/firm...
That looks to be doing the same thing that stacks.c:call32() does.
BTW, are you reserving the relocated code or are you only doing this during the init phase?
The 'high bios' functions should be accessible all the time basically. So, the relocated code needs to be marked as e820-reserved memory -- I suppose that should do the trick then?
Yes, but of course that means the OS can't use the memory then. Why does the code need to be in high memory - why not just have it in the f-segment?
With possible future extensions to the BIOS, the f-segment may not provide enough space and so we can open up 'the world' using the high memory areas. Reserving for example 256kb out of 1 GB seems negligible...
Stefan
On Sat, Nov 20, 2010 at 01:40:12PM -0500, Stefan Berger wrote:
On 11/20/2010 01:28 PM, Kevin O'Connor wrote:
Yes, but of course that means the OS can't use the memory then. Why does the code need to be in high memory - why not just have it in the f-segment?
With possible future extensions to the BIOS, the f-segment may not provide enough space and so we can open up 'the world' using the high memory areas. Reserving for example 256kb out of 1 GB seems negligible...
Right - that's why SeaBIOS implements code relocation. The current relocation stuff is designed around separating out the initialization code from the run-time code - if all of it is going to be reserved anyway then that doesn't make much sense.
Maybe it would help if you describe what it is you are trying to do, and how big the code is going to be.
Cheers, -Kevin
On 11/20/2010 02:15 PM, Kevin O'Connor wrote:
On Sat, Nov 20, 2010 at 01:40:12PM -0500, Stefan Berger wrote:
On 11/20/2010 01:28 PM, Kevin O'Connor wrote:
Yes, but of course that means the OS can't use the memory then. Why does the code need to be in high memory - why not just have it in the f-segment?
With possible future extensions to the BIOS, the f-segment may not provide enough space and so we can open up 'the world' using the high memory areas. Reserving for example 256kb out of 1 GB seems negligible...
Right - that's why SeaBIOS implements code relocation. The current relocation stuff is designed around separating out the initialization code from the run-time code - if all of it is going to be reserved anyway then that doesn't make much sense.
Maybe it would help if you describe what it is you are trying to do, and how big the code is going to be.
The idea would be to contribute TCG extensions as previously add to the Bochs BIOS -- that ended up filling up the segments.
http://xenbits.xensource.com/xen-4.0-testing.hg?file/e9156d9d996b/tools/firm...
Stefan
Cheers, -Kevin
On Sat, Nov 20, 2010 at 02:20:50PM -0500, Stefan Berger wrote:
On 11/20/2010 02:15 PM, Kevin O'Connor wrote:
Maybe it would help if you describe what it is you are trying to do, and how big the code is going to be.
The idea would be to contribute TCG extensions as previously add to the Bochs BIOS -- that ended up filling up the segments.
http://xenbits.xensource.com/xen-4.0-testing.hg?file/e9156d9d996b/tools/firm...
Wow - I only became aware of Xen's copy of Bochs bios a few weeks ago - there's a ton of duplication of effort here between Xen Bios and SeaBIOS.
As for the size, if this is ported to SeaBIOS, I'd like to see what it looks like without any special high-memory execution first.
-Kevin
On 11/20/2010 01:28 PM, Kevin O'Connor wrote:
On Sat, Nov 20, 2010 at 01:18:18PM -0500, Stefan Berger wrote:
On 11/20/2010 01:05 PM, Kevin O'Connor wrote:
Is it something like stacks.c:call32() or is it via SMM?
The way it works is that there is a jumptable with entries to the function in the 'high bios'. That jumptable along with all the other 32 bit code gets relocated to upper memory and in the 'lower BIOS' I keep a pointer to the jumptable in the 'high bios' for the upcall code to see. It's basically similar to what I have previously contributed to Bochs BIOS in Xen, just that the upcall code can deal with parameter passed via registers or a limited number on the stack.
http://xenbits.xensource.com/xen-4.0-testing.hg?file/e9156d9d996b/tools/firm...
That looks to be doing the same thing that stacks.c:call32() does.
As it looks, this function allows no parameters to be passed. What I would be adding is a function allowing transitioning from 16 bit to 32 bit with >3 parameters (6 currently). There's some nastiness involved due to the 'ret + n' of functions being called with stack parameters, which starts with 4 parameters, and which does need explicit code in the transitioning function to fix up the stack as the caller expects it. As said, I am using a call table for transitioning that but calls are rather invisible from the C code perspective due to some tricks with #defines.
The assumption that the BIOS would fill up is not given yet, as was the case for Bochs... but it's rather easy now to support the extension into 32 bit space.
Stefan
BTW, are you reserving the relocated code or are you only doing this during the init phase?
The 'high bios' functions should be accessible all the time basically. So, the relocated code needs to be marked as e820-reserved memory -- I suppose that should do the trick then?
Yes, but of course that means the OS can't use the memory then. Why does the code need to be in high memory - why not just have it in the f-segment?
-Kevin
On Mon, Nov 22, 2010 at 10:12:38AM -0500, Stefan Berger wrote:
On 11/20/2010 01:28 PM, Kevin O'Connor wrote:
That looks to be doing the same thing that stacks.c:call32() does.
As it looks, this function allows no parameters to be passed. What I would be adding is a function allowing transitioning from 16 bit to 32 bit with >3 parameters (6 currently). There's some nastiness involved due to the 'ret + n' of functions being called with stack parameters, which starts with 4 parameters, and which does need explicit code in the transitioning function to fix up the stack as the caller expects it. As said, I am using a call table for transitioning that but calls are rather invisible from the C code perspective due to some tricks with #defines.
It wont be a big deal to pass one or two parameters through call32() - SeaBIOS has gcc use register passing by default so it just requires setting %eax/%ecx. If more than a couple parameters are needed, then the caller should populate a struct on the stack and then pass a pointer to the struct.
-Kevin
NMIs are blocked by default agter entering SMM.
"Kevin O'Connor" kevin@koconnor.net wrote:
On Fri, Nov 19, 2010 at 03:39:58PM -0800, H. Peter Anvin wrote:
On 11/19/2010 02:58 PM, Gerd Hoffmann wrote:
On 09/23/10 14:56, Kevin O'Connor wrote:
I suppose one could write a simple SMI handler that just set the
OHCI
cmdstatus bits. That probably wouldn't be too hard and it
wouldn't be
too complex.
Hi folks,
What is the current state of affairs? Sooner or later we'll need a
solution for the pci-bar-access-from-real-mode issue ...
I looked briefly at the usb3 specs and I think it is impossible to
drive
a xHCI adapter without access to the PCI bar.
Looking briefly myself, it does look like accessing the doorbell registers will be necessary.
Also AHCI support needs access to the PCI bar to submit commands
and
check status.
Yeah - it looks that way to me as well.
Would INT 15h, AH=87h do the job well enough? Otherwise it's
probably
SMM or bust...
I don't think int1587 would work reliably. So, I'd say SMM would be needed.
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode. The BIOS handler could then do its work and manually return the CPU to its initial state before returning to the guest. The BIOS would need to ensure that it didn't allow interrupts (or NMIs) while in this mode, but that's possible. One would probably want to ensure that the BIOS didn't touch any non-BIOS owned memory in this state as well, but that's also possible.
-Kevin
Hi,
Would INT 15h, AH=87h do the job well enough?
Someone mentioned earlier in this thread that one does 16bit memory access whereas pci memory bars are usually accessed using 32bit read/writes ...
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode.
Hmm, how about having a virtual "I/O bounce" device? Allocate two dwords in I/O space. One dword for the address, one for the data. reads and writes to the data register will be bounced to the address written into the address register.
On real hardware seabios could emulate this using SMM.
On virtual hardware qemu could emulate this so we don't need SMM support in kvm.
From a security point of view it might not be the best idea though.
Comments?
cheers, Gerd
On Mon, Nov 22, 2010 at 11:52:56AM +0100, Gerd Hoffmann wrote:
I suppose one could implement a simple SMM gateway - write a magic IO bit to invoke the SMM handler, have the SMM handler backup the cpu state somewhere in BIOS owned memory, and then leave SMM mode with execution at a BIOS handler running in 32bit flat mode.
Hmm, how about having a virtual "I/O bounce" device? Allocate two dwords in I/O space. One dword for the address, one for the data. reads and writes to the data register will be bounced to the address written into the address register.
It could work. However, having the ability to go into full 32bit mode would be more flexible.
On real hardware seabios could emulate this using SMM.
On virtual hardware qemu could emulate this so we don't need SMM support in kvm.
How hard would it be to add SMM support into kvm?
From a security point of view it might not be the best idea though.
If a program has access to iospace, it's basically fully privileged anyway, so I don't think this is a problem. (For example, the old 16bit DMA registers are fully programmed from iospace.)
-Kevin
On 11/22/10 14:47, Kevin O'Connor wrote:
On Mon, Nov 22, 2010 at 11:52:56AM +0100, Gerd Hoffmann wrote:
[ access pci bars from real mode ]
Hmm, how about having a virtual "I/O bounce" device? Allocate two dwords in I/O space. One dword for the address, one for the data. reads and writes to the data register will be bounced to the address written into the address register.
It could work. However, having the ability to go into full 32bit mode would be more flexible.
Indeed, and it would also allow to move bios code into high memory.
On real hardware seabios could emulate this using SMM.
On virtual hardware qemu could emulate this so we don't need SMM support in kvm.
How hard would it be to add SMM support into kvm?
Dunno. As I understand it the biggest issue is that kvm needs complete instruction emulation for big real mode as intel vmx supports protected mode only. Correct Avi?
cheers, Gerd
On 11/22/2010 04:49 PM, Gerd Hoffmann wrote:
On real hardware seabios could emulate this using SMM.
On virtual hardware qemu could emulate this so we don't need SMM support in kvm.
How hard would it be to add SMM support into kvm?
Dunno. As I understand it the biggest issue is that kvm needs complete instruction emulation for big real mode as intel vmx supports protected mode only. Correct Avi?
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
However, we have a large deployed base with no SMM support, so we need a fallback if SMM is not available. It's also tricky to probe for working SMM, I don't think there's a cpuid bit for that.
On 11/22/2010 07:45 AM, Avi Kivity wrote:
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
However, we have a large deployed base with no SMM support, so we need a fallback if SMM is not available. It's also tricky to probe for working SMM, I don't think there's a cpuid bit for that.
All real CPUs 586+ support SMM, so a CPUID bit wouldn't be applicable.
That being said, SMM has to be activated from the chipset, so some kind of ID bit could be put in there.
-hpa
On 11/22/2010 06:50 PM, H. Peter Anvin wrote:
On 11/22/2010 07:45 AM, Avi Kivity wrote:
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
However, we have a large deployed base with no SMM support, so we need a fallback if SMM is not available. It's also tricky to probe for working SMM, I don't think there's a cpuid bit for that.
All real CPUs 586+ support SMM, so a CPUID bit wouldn't be applicable.
That being said, SMM has to be activated from the chipset, so some kind of ID bit could be put in there.
Well, the chipset we emulate does support SMM.
I guess we could have a fwcfg entry that says whether SMM actually works.
On Mon, Nov 22, 2010 at 05:45:49PM +0200, Avi Kivity wrote:
On 11/22/2010 04:49 PM, Gerd Hoffmann wrote:
Dunno. As I understand it the biggest issue is that kvm needs complete instruction emulation for big real mode as intel vmx supports protected mode only. Correct Avi?
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
The big real mode support needed for SMM is no greater than the big real mode supported needed for option roms. Since option roms work today, I'm not sure what more is needed. (I recall there being a problem with %eip>64K, but there's no reason to do that in SMM so I don't think it is an issue.)
However, we have a large deployed base with no SMM support, so we need a fallback if SMM is not available. It's also tricky to probe for working SMM, I don't think there's a cpuid bit for that.
There's already a check for this today - if a specific PCI device exists then seabios tries to setup SMM, otherwise it doesn't.
-Kevin
On 11/23/2010 02:24 AM, Kevin O'Connor wrote:
On Mon, Nov 22, 2010 at 05:45:49PM +0200, Avi Kivity wrote:
On 11/22/2010 04:49 PM, Gerd Hoffmann wrote:
Dunno. As I understand it the biggest issue is that kvm needs complete instruction emulation for big real mode as intel vmx supports protected mode only. Correct Avi?
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
The big real mode support needed for SMM is no greater than the big real mode supported needed for option roms. Since option roms work today, I'm not sure what more is needed. (I recall there being a problem with %eip>64K, but there's no reason to do that in SMM so I don't think it is an issue.)
Okay, then it's simply a matter of implementing SMM entry and RSM, adding save/restore support, and interfaces for asserting #SMI.
However, we have a large deployed base with no SMM support, so we need a fallback if SMM is not available. It's also tricky to probe for working SMM, I don't think there's a cpuid bit for that.
There's already a check for this today - if a specific PCI device exists then seabios tries to setup SMM, otherwise it doesn't.
Which PCI device is that?
When you say "tries", do you mean it allows for failure?
On Tue, Nov 23, 2010 at 08:22:55AM +0200, Avi Kivity wrote:
On 11/23/2010 02:24 AM, Kevin O'Connor wrote:
There's already a check for this today - if a specific PCI device exists then seabios tries to setup SMM, otherwise it doesn't.
Which PCI device is that?
When you say "tries", do you mean it allows for failure?
If PCI_DEVICE_ID_INTEL_82371AB_3 and PCI_DEVICE_ID_INTEL_82441 are found then seabios programs the SMM. If either device is not found, then it wont attempt to program it. Right now, one of these devices isn't on kvm, and so seabios doesn't try to program smm.
-Kevin
On Mon, Nov 22, 2010 at 05:45:49PM +0200, Avi Kivity wrote:
On 11/22/2010 04:49 PM, Gerd Hoffmann wrote:
On real hardware seabios could emulate this using SMM.
On virtual hardware qemu could emulate this so we don't need SMM support in kvm.
How hard would it be to add SMM support into kvm?
Dunno. As I understand it the biggest issue is that kvm needs complete instruction emulation for big real mode as intel vmx supports protected mode only. Correct Avi?
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
Do we? What about support for remapping of 0xa0000 address from framebuffer to RAM during SMM. If our reading of spec is correct it should be done per vcpu. Currently memory slots are shared between vcpus.
We can, of course, put SMM code in other memory address and mark it as reserver in E820 though.
-- Gleb.
On 11/23/2010 09:08 AM, Gleb Natapov wrote:
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
Do we? What about support for remapping of 0xa0000 address from framebuffer to RAM during SMM. If our reading of spec is correct it should be done per vcpu. Currently memory slots are shared between vcpus.
Yes. We could define a set of alternate memory slots to be used when SMM is active. The mmu is already prepared (like we support vcpus with different paging modes simultaneously).
On Tue, Nov 23, 2010 at 09:38:58AM +0200, Avi Kivity wrote:
On 11/23/2010 09:08 AM, Gleb Natapov wrote:
Correct. Note, it's likely that we have almost everything covered already, so it's mostly testing (beyond implementing SMM entry/exit).
Do we? What about support for remapping of 0xa0000 address from framebuffer to RAM during SMM. If our reading of spec is correct it should be done per vcpu. Currently memory slots are shared between vcpus.
Yes. We could define a set of alternate memory slots to be used when SMM is active. The mmu is already prepared (like we support vcpus with different paging modes simultaneously).
But memory slots resides below mmu. The responsible of mmu is to translate gva to gpa. After that memory slots are used to translate gpa into hva and at this point it is not per vcpu. With SMM one vcpu can generate MMIO access and another one memory access with the same gpa.
-- Gleb.
On 11/23/2010 09:45 AM, Gleb Natapov wrote:
Yes. We could define a set of alternate memory slots to be used when SMM is active. The mmu is already prepared (like we support vcpus with different paging modes simultaneously).
But memory slots resides below mmu. The responsible of mmu is to translate gva to gpa. After that memory slots are used to translate gpa into hva and at this point it is not per vcpu. With SMM one vcpu can generate MMIO access and another one memory access with the same gpa.
The mmu would translate gva to a (gpa, smm) pair (when tdp is enabled, translate gpa or ngpa to (gpa, smm). gfn_to_page() translates a (gpa, smm) pair to a struct page.
On 11/23/2010 09:48 AM, Avi Kivity wrote:
On 11/23/2010 09:45 AM, Gleb Natapov wrote:
Yes. We could define a set of alternate memory slots to be used when SMM is active. The mmu is already prepared (like we support vcpus with different paging modes simultaneously).
But memory slots resides below mmu. The responsible of mmu is to translate gva to gpa. After that memory slots are used to translate gpa into hva and at this point it is not per vcpu. With SMM one vcpu can generate MMIO access and another one memory access with the same gpa.
The mmu would translate gva to a (gpa, smm) pair (when tdp is enabled, translate gpa or ngpa to (gpa, smm). gfn_to_page() translates a (gpa, smm) pair to a struct page.
In other words, SMIACT# is an address bit. We could encode it in bit 63 of gpa_t.
On Tue, Nov 23, 2010 at 09:48:58AM +0200, Avi Kivity wrote:
On 11/23/2010 09:45 AM, Gleb Natapov wrote:
Yes. We could define a set of alternate memory slots to be used when SMM is active. The mmu is already prepared (like we support vcpus with different paging modes simultaneously).
But memory slots resides below mmu. The responsible of mmu is to translate gva to gpa. After that memory slots are used to translate gpa into hva and at this point it is not per vcpu. With SMM one vcpu can generate MMIO access and another one memory access with the same gpa.
The mmu would translate gva to a (gpa, smm) pair (when tdp is enabled, translate gpa or ngpa to (gpa, smm). gfn_to_page() translates a (gpa, smm) pair to a struct page.
Actually smm is a vcpu state, so only gfn_to_pfn will have to be changed to get vcpu as a parameter (or is_smm flag, although this look like very x86ish thing for common code where gfn_to_pfn resides).
-- Gleb.
On 11/23/2010 10:21 AM, Gleb Natapov wrote:
The mmu would translate gva to a (gpa, smm) pair (when tdp is enabled, translate gpa or ngpa to (gpa, smm). gfn_to_page() translates a (gpa, smm) pair to a struct page.
Actually smm is a vcpu state, so only gfn_to_pfn will have to be changed to get vcpu as a parameter (or is_smm flag, although this look like very x86ish thing for common code where gfn_to_pfn resides).
Yes, even simpler. We'll need to add smm to kvm_mmu_page_role so page tables don't get confused.
On Tue, Nov 23, 2010 at 12:32:04PM +0200, Avi Kivity wrote:
On 11/23/2010 10:21 AM, Gleb Natapov wrote:
The mmu would translate gva to a (gpa, smm) pair (when tdp is enabled, translate gpa or ngpa to (gpa, smm). gfn_to_page() translates a (gpa, smm) pair to a struct page.
Actually smm is a vcpu state, so only gfn_to_pfn will have to be changed to get vcpu as a parameter (or is_smm flag, although this look like very x86ish thing for common code where gfn_to_pfn resides).
Yes, even simpler. We'll need to add smm to kvm_mmu_page_role so page tables don't get confused.
And what about tdp? kvm_mmu_page_role is not used there, no?
-- Gleb.
On 11/23/2010 03:29 PM, Gleb Natapov wrote:
On Tue, Nov 23, 2010 at 12:32:04PM +0200, Avi Kivity wrote:
On 11/23/2010 10:21 AM, Gleb Natapov wrote:
The mmu would translate gva to a (gpa, smm) pair (when tdp is enabled, translate gpa or ngpa to (gpa, smm). gfn_to_page() translates a (gpa, smm) pair to a struct page.
Actually smm is a vcpu state, so only gfn_to_pfn will have to be changed to get vcpu as a parameter (or is_smm flag, although this look like very x86ish thing for common code where gfn_to_pfn resides).
Yes, even simpler. We'll need to add smm to kvm_mmu_page_role so page tables don't get confused.
And what about tdp? kvm_mmu_page_role is not used there, no?
It is used.
On 9/23/10 3:16 AM, Kevin O'Connor wrote:
Using SMI is something I've thought a little about. It does have some snags: SMI programming is chipset specific on real hardware so one can't deploy a single solution for all coreboot users;
coreboot has some fairly generic SMI handler code that runs in protected mode. Some of the code parts are chipset specific and some are CPU specific, but those are no magic. Many x86 firmware implementations today allow their subsystems to add their own code to the SMI handler. coreboot could provide an interface that would allow SeaBIOS to hook its code up the very same way. Left alone the question if the USB stack shouldn't be migrated into coreboot completely rather than potentially opening a huge security hole and another API to keep stable.
using an SMI to get out of vm86 mode requires the BIOS to emulate all memory accesses to user memory (manually walking the page table, forcing page faults) which is tricky;
Whereas an alternative could be to have vm86 users provide their own USB stack.
How do other BIOSes solve the problem?
Stefan
On Mon, Sep 27, 2010 at 06:29:31PM +0200, Stefan Reinauer wrote:
Left alone the question if the USB stack shouldn't be migrated into coreboot completely rather than potentially opening a huge security hole and another API to keep stable.
One can't do the full USB stack in SMI - if nothing else, seabios would need to translate the disk access requests into coreboot SMI requests. At that point, there's going to be an API and probably all the same security concerns.
However, it's a valid question. I do kinda like the way SeaBIOS can do USB without needing SMI today. Only OHCI bulk has been an issue so far. (Though OHCI keyboard leds would also be a problem.) Using SMI for OHCI bulk seems like "using a sledgehammer to kill a fly" to me. In particular, I'd guess most people would be using ehci bulk today.
using an SMI to get out of vm86 mode requires the BIOS to emulate all memory accesses to user memory (manually walking the page table, forcing page faults) which is tricky;
Whereas an alternative could be to have vm86 users provide their own USB stack.
It's possible to support OHCI bulk by switching into protected mode; failing any requests made while in vm86 mode. Two problems: freedos by default uses vm86 mode; there's no good way to know whether to return in real mode or bigreal mode.
How do other BIOSes solve the problem?
That's a good question, and I don't know the answer. I would guess they have an SMI keyboard handler that does some of the bulk work too.
-Kevin
On 09/27/2010 05:21 PM, Kevin O'Connor wrote:
It's possible to support OHCI bulk by switching into protected mode; failing any requests made while in vm86 mode. Two problems: freedos by default uses vm86 mode; there's no good way to know whether to return in real mode or bigreal mode.
How do other BIOSes solve the problem?
That's a good question, and I don't know the answer. I would guess they have an SMI keyboard handler that does some of the bulk work too.
That is my understanding.
-hpa
On 09/22/2010 08:21 PM, H. Peter Anvin wrote:
On 09/22/2010 05:52 AM, Kevin O'Connor wrote:
On Wed, Sep 22, 2010 at 06:40:58AM +0200, Peter Stuge wrote:
Kevin O'Connor wrote:
When in 16bit mode, one can only reliably access the first 1Meg of ram.
Flat real mode?
The BIOS can put the machine in big real mode when it launches the OS, but it can't expect that it will always be called in big real mode. The BIOS could attempt to transition to 32bit mode (or big real mode) in the disk handler, but it may have been called in vm86 mode which would then effectively cause a crash. (It also wipes out the hidden segment registers which may confuse the OS.) Use of vm86 mode is not uncommon - freedos does it and so does (I'm told) Linux.
The standard way to deal with this in the BIOS (and *only* the BIOS can do this!) is to trap into SMM and have an SMI handler do the I/O. Taking an SMI drops the CPU into big real mode regardless of what the previous CPU mode was.
One problem is that kvm doesn't implement SMM at this point.
While we could do it (not going to be pleasant), it's not going to be present on many deployed machines. I also don't see a way to detect SMM (I guess we could expose it via fwcfg).
What about the ISA DMA engine?
On 09/27/2010 10:00 AM, Avi Kivity wrote:
The standard way to deal with this in the BIOS (and *only* the BIOS can do this!) is to trap into SMM and have an SMI handler do the I/O. Taking an SMI drops the CPU into big real mode regardless of what the previous CPU mode was.
One problem is that kvm doesn't implement SMM at this point.
While we could do it (not going to be pleasant), it's not going to be present on many deployed machines. I also don't see a way to detect SMM (I guess we could expose it via fwcfg).
What about the ISA DMA engine?
The ISA DMA engine can only access the bottom 16 MiB since it only has 24 address bits.
As far as KVM is concerned, if KVM doesn't wish to implement SMM (which really isn't all that hard -- it's pretty much a matter of dumping the state and undumping it on RSM; since SMM code is restricted to the firmware it doesn't necessarily have to be compatible with the native CPU) KVM could simply implement a custom memory-moving device -- which would be faster to boot.
-hpa
On Mon, Sep 27, 2010 at 10:33:49AM -0700, H. Peter Anvin wrote:
On 09/27/2010 10:00 AM, Avi Kivity wrote:
What about the ISA DMA engine?
The ISA DMA engine can only access the bottom 16 MiB since it only has 24 address bits.
As far as KVM is concerned, if KVM doesn't wish to implement SMM (which really isn't all that hard -- it's pretty much a matter of dumping the state and undumping it on RSM; since SMM code is restricted to the firmware it doesn't necessarily have to be compatible with the native CPU) KVM could simply implement a custom memory-moving device -- which would be faster to boot.
I didn't think kvm uses ohci today. This issue isn't a problem at all with uhci or ehci.
-Kevin
On 09/28/2010 02:30 AM, Kevin O'Connor wrote:
On Mon, Sep 27, 2010 at 10:33:49AM -0700, H. Peter Anvin wrote:
On 09/27/2010 10:00 AM, Avi Kivity wrote:
What about the ISA DMA engine?
The ISA DMA engine can only access the bottom 16 MiB since it only has 24 address bits.
As far as KVM is concerned, if KVM doesn't wish to implement SMM (which really isn't all that hard -- it's pretty much a matter of dumping the state and undumping it on RSM; since SMM code is restricted to the firmware it doesn't necessarily have to be compatible with the native CPU) KVM could simply implement a custom memory-moving device -- which would be faster to boot.
I didn't think kvm uses ohci today. This issue isn't a problem at all with uhci or ehci.
Ok. virtio happens to use PIO so it's safe. lsi53c895a appears to dual map its registers to both an mmio and io BAR.
We'll probably have a problem with assigned GPUs, but these have their own firmware.
On 09/27/2010 07:33 PM, H. Peter Anvin wrote:
On 09/27/2010 10:00 AM, Avi Kivity wrote:
The standard way to deal with this in the BIOS (and *only* the BIOS can do this!) is to trap into SMM and have an SMI handler do the I/O. Taking an SMI drops the CPU into big real mode regardless of what the previous CPU mode was.
One problem is that kvm doesn't implement SMM at this point.
While we could do it (not going to be pleasant), it's not going to be present on many deployed machines. I also don't see a way to detect SMM (I guess we could expose it via fwcfg).
What about the ISA DMA engine?
The ISA DMA engine can only access the bottom 16 MiB since it only has 24 address bits.
qemu's hw/dma.c appears to support 31 bits:
int DMA_read_memory (int nchan, void *buf, int pos, int len) { struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; target_phys_addr_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
(which may still not be enough)
As far as KVM is concerned, if KVM doesn't wish to implement SMM (which really isn't all that hard -- it's pretty much a matter of dumping the state and undumping it on RSM; since SMM code is restricted to the firmware it doesn't necessarily have to be compatible with the native CPU)
SMM runs in big real mode, which we're only just starting to support on Intel. Effectively it means we have to emulate every instruction. Dumping the state and restoring it is the simple part.
KVM could simply implement a custom memory-moving device -- which would be faster to boot.
A virtio dma engine would be useful for other things as well.
On 09/28/2010 12:27 AM, Avi Kivity wrote:
SMM runs in big real mode, which we're only just starting to support on Intel. Effectively it means we have to emulate every instruction. Dumping the state and restoring it is the simple part.
SMM *starts* in big real mode; there is no requirement to stay in that mode, FWIW
-hpa
On 09/28/2010 07:54 PM, H. Peter Anvin wrote:
On 09/28/2010 12:27 AM, Avi Kivity wrote:
SMM runs in big real mode, which we're only just starting to support on Intel. Effectively it means we have to emulate every instruction. Dumping the state and restoring it is the simple part.
SMM *starts* in big real mode; there is no requirement to stay in that mode, FWIW
I really hate tailoring the firmware code to kvm capabilities. SMM should work without restrictions on the code you can run in it.
On Wed, Sep 29, 2010 at 10:39:45AM +0200, Avi Kivity wrote:
On 09/28/2010 07:54 PM, H. Peter Anvin wrote:
On 09/28/2010 12:27 AM, Avi Kivity wrote:
SMM runs in big real mode, which we're only just starting to support on Intel. Effectively it means we have to emulate every instruction. Dumping the state and restoring it is the simple part.
SMM *starts* in big real mode; there is no requirement to stay in that mode, FWIW
I really hate tailoring the firmware code to kvm capabilities. SMM should work without restrictions on the code you can run in it.
Heh, I really hate real mode, so going into 32bit mode sounds good to me anyway. :-)
-Kevin
On 09/29/2010 04:45 AM, Kevin O'Connor wrote:
On Wed, Sep 29, 2010 at 10:39:45AM +0200, Avi Kivity wrote:
On 09/28/2010 07:54 PM, H. Peter Anvin wrote:
On 09/28/2010 12:27 AM, Avi Kivity wrote:
SMM runs in big real mode, which we're only just starting to support on Intel. Effectively it means we have to emulate every instruction. Dumping the state and restoring it is the simple part.
SMM *starts* in big real mode; there is no requirement to stay in that mode, FWIW
I really hate tailoring the firmware code to kvm capabilities. SMM should work without restrictions on the code you can run in it.
Heh, I really hate real mode, so going into 32bit mode sounds good to me anyway. :-)
Yeah... big real mode is rather expensive in terms of the 66 and 67 prefixes you end up littering the code with just to be in the mode you actually want. Better then to load a GDT, flip CR0.PE, and go to a 32-bit code segment anyway.
-hpa
On Wed, Sep 29, 2010 at 08:19:33AM -0700, H. Peter Anvin wrote:
Yeah... big real mode is rather expensive in terms of the 66 and 67 prefixes you end up littering the code with just to be in the mode you actually want. Better then to load a GDT, flip CR0.PE, and go to a 32-bit code segment anyway.
That brings up an interesting question. Do you know if instruction prefixes result in slower cpu execution? I know they bloat the code, but it's not been clear to me if there is a speed impact (besides a small cost to insn fetching). Real mode execution is documented to be slow, but it's unclear if using regular 32bit operations (via prefixes) would be even slower, the same, or a little faster.
BTW, I calculate that prefixes represent 12% of the seabios 16bit code size (4720 of 38920 bytes). I've found the code size with gcc (using prefixes) was smaller than the code size was with bcc - largely due to the optimizations and improved code structure that gcc enabled.
-Kevin
On 09/29/2010 08:51 PM, Kevin O'Connor wrote:
On Wed, Sep 29, 2010 at 08:19:33AM -0700, H. Peter Anvin wrote:
Yeah... big real mode is rather expensive in terms of the 66 and 67 prefixes you end up littering the code with just to be in the mode you actually want. Better then to load a GDT, flip CR0.PE, and go to a 32-bit code segment anyway.
That brings up an interesting question. Do you know if instruction prefixes result in slower cpu execution? I know they bloat the code, but it's not been clear to me if there is a speed impact (besides a small cost to insn fetching). Real mode execution is documented to be slow, but it's unclear if using regular 32bit operations (via prefixes) would be even slower, the same, or a little faster.
BTW, I calculate that prefixes represent 12% of the seabios 16bit code size (4720 of 38920 bytes). I've found the code size with gcc (using prefixes) was smaller than the code size was with bcc - largely due to the optimizations and improved code structure that gcc enabled.
-Kevin
On older processors they do slow down the CPU, on modern CPUs they generally don't, except for icache footprint, of course.
In general real mode execution is no slower than the corresponding protected mode.
I worked for a while on a 16-bit gcc backend... I kind of stopped because of perceived lack of interest, and it wasn't fully usable yet, but perhaps Seabios would be enough of a reason. It seemed to produce code about 15% smaller than gcc with prefixes.
-hpa
On Wed, Sep 29, 2010 at 09:15:11PM -0700, H. Peter Anvin wrote:
On 09/29/2010 08:51 PM, Kevin O'Connor wrote:
On Wed, Sep 29, 2010 at 08:19:33AM -0700, H. Peter Anvin wrote: That brings up an interesting question. Do you know if instruction prefixes result in slower cpu execution? I know they bloat the code, but it's not been clear to me if there is a speed impact (besides a small cost to insn fetching). Real mode execution is documented to be slow, but it's unclear if using regular 32bit operations (via prefixes) would be even slower, the same, or a little faster.
On older processors they do slow down the CPU, on modern CPUs they generally don't, except for icache footprint, of course.
In general real mode execution is no slower than the corresponding protected mode.
Sorry - I meant: 16bit code segments are documented to be slow, but it's unclear if using regular 32bit instructions in them (via prefixes) would be even slower, the same, or faster.
BTW, I calculate that prefixes represent 12% of the seabios 16bit code size (4720 of 38920 bytes). I've found the code size with gcc (using prefixes) was smaller than the code size was with bcc - largely due to the optimizations and improved code structure that gcc enabled.
[...]
I worked for a while on a 16-bit gcc backend... I kind of stopped because of perceived lack of interest, and it wasn't fully usable yet, but perhaps Seabios would be enough of a reason. It seemed to produce code about 15% smaller than gcc with prefixes.
[...]
Oh, yes, there is of course also OpenWatcom, which I personally had high hopes for ... and it is quite a good 16-bit compiler, it's just that I've found the OW community to not always have goals compatible with my needs, which of course are for a decent cross-compiler.
I don't think either would be worthwhile just to shrink the 16bit code size.
Granted, the seabios memory macros (eg, GET_GLOBAL, GET_FARVAR, GET_FLATPTR) are ugly. However, since SeaBIOS handles real-mode, bigreal-mode, 16bit protected mode, 32bit "flat" mode, 32bit mode with segments, and 32bit segmented PIC mode, I doubt any normal 16bit compiler could handle all of these without macros anyway.
-Kevin
On 09/29/2010 08:51 PM, Kevin O'Connor wrote:
On Wed, Sep 29, 2010 at 08:19:33AM -0700, H. Peter Anvin wrote:
Yeah... big real mode is rather expensive in terms of the 66 and 67 prefixes you end up littering the code with just to be in the mode you actually want. Better then to load a GDT, flip CR0.PE, and go to a 32-bit code segment anyway.
That brings up an interesting question. Do you know if instruction prefixes result in slower cpu execution? I know they bloat the code, but it's not been clear to me if there is a speed impact (besides a small cost to insn fetching). Real mode execution is documented to be slow, but it's unclear if using regular 32bit operations (via prefixes) would be even slower, the same, or a little faster.
BTW, I calculate that prefixes represent 12% of the seabios 16bit code size (4720 of 38920 bytes). I've found the code size with gcc (using prefixes) was smaller than the code size was with bcc - largely due to the optimizations and improved code structure that gcc enabled.
Oh, yes, there is of course also OpenWatcom, which I personally had high hopes for ... and it is quite a good 16-bit compiler, it's just that I've found the OW community to not always have goals compatible with my needs, which of course are for a decent cross-compiler.
-hpa
On 09/30/2010 05:51 AM, Kevin O'Connor wrote:
On Wed, Sep 29, 2010 at 08:19:33AM -0700, H. Peter Anvin wrote:
Yeah... big real mode is rather expensive in terms of the 66 and 67 prefixes you end up littering the code with just to be in the mode you actually want. Better then to load a GDT, flip CR0.PE, and go to a 32-bit code segment anyway.
That brings up an interesting question. Do you know if instruction prefixes result in slower cpu execution?
Is there really a performance problem in seabios?
On modern processors the only problems are with "length-changing prefixes", a prefix that changes the instruction length. Usually when an immediate changes from 16 bits to 32 bits or vice versa.
On Sat, Oct 02, 2010 at 11:39:06AM +0200, Avi Kivity wrote:
On 09/30/2010 05:51 AM, Kevin O'Connor wrote:
On Wed, Sep 29, 2010 at 08:19:33AM -0700, H. Peter Anvin wrote:
Yeah... big real mode is rather expensive in terms of the 66 and 67 prefixes you end up littering the code with just to be in the mode you actually want. Better then to load a GDT, flip CR0.PE, and go to a 32-bit code segment anyway.
That brings up an interesting question. Do you know if instruction prefixes result in slower cpu execution?
Is there really a performance problem in seabios?
No. I was asking only out of curiosity. Even if prefixes slow 16bit mode, a normal SeaBIOS boot runs very little 16bit code.
-Kevin