Hi,
I have a really tough challenge for you: I need a global variable in v3. Global means that it has to be accessible from all of stage1/stage2 code (maybe except initram).
So far I only see one unacceptably hackish solution: Pass a pointer to the global variable to every function in the codebase. It works, but I'd rather not post a patch doing this because it violates my aesthetic sense, especially because the variable is used in only very few functions, however those are called all over the place.
A possible alternative would be a getter/setter function for the variable. I have no problem with that, but the getter/setter function has to store the location of the variable somewhere, and that can't be solved except through pointer passing like above.
There must be a solution out there, I just can't see it.
Regards, Carl-Daniel
On Mon, Feb 04, 2008 at 02:52:05PM +0100, Carl-Daniel Hailfinger wrote:
I have a really tough challenge for you: I need a global variable in v3.
Why?
//Peter
On 04.02.2008 16:28, Peter Stuge wrote:
On Mon, Feb 04, 2008 at 02:52:05PM +0100, Carl-Daniel Hailfinger wrote:
I have a really tough challenge for you: I need a global variable in v3.
Why?
It's a pointer to the printk log buffer. That way, we have printk as soon as we enter stage 1, even before the Super I/O is initialized. As an added benefit, we can make the coreboot log available to payloads.
Regards, Carl-Daniel
On Mon, Feb 04, 2008 at 04:52:56PM +0100, Carl-Daniel Hailfinger wrote:
On 04.02.2008 16:28, Peter Stuge wrote:
On Mon, Feb 04, 2008 at 02:52:05PM +0100, Carl-Daniel Hailfinger wrote:
I have a really tough challenge for you: I need a global variable in v3.
Why?
It's a pointer to the printk log buffer. That way, we have printk as soon as we enter stage 1, even before the Super I/O is initialized. As an added benefit, we can make the coreboot log available to payloads.
That would be awesome. I'd love to see it show up in dmesg...
Thanks, Ward.
So, this is an example of the reason for the (void *) param I was suggesting some time back. Such needs come up.
One option is to have a convention that globals are at the base of the stack, rounded to 64k.
e.g. %esp & 0xffff0000 is where globals live.
ron
ron minnich wrote:
So, this is an example of the reason for the (void *) param I was suggesting some time back. Such needs come up.
One option is to have a convention that globals are at the base of the stack, rounded to 64k.
e.g. %esp & 0xffff0000 is where globals live.
Let's just put the buffer to a well known address. We're trying to add a flexibility here that is just ballast.
The buffer might need to change its position, ie when we are going from CAR to real RAM. Who knows. But other than that...
On Feb 4, 2008 8:22 AM, Stefan Reinauer stepan@coresystems.de wrote:
Let's just put the buffer to a well known address. We're trying to add a flexibility here that is just ballast.
OK, good point.
So far our dedicated addresses are these: page 0 -- for vm86 page 1 -- for vm86 0x88000 -- 0x8ffff -- stack. (stack should probably move to 0x98000) Then put log buffer at 0x90000?
ron
On 04.02.2008 17:26, ron minnich wrote:
On Feb 4, 2008 8:22 AM, Stefan Reinauer stepan@coresystems.de wrote:
Let's just put the buffer to a well known address. We're trying to add a flexibility here that is just ballast.
It's not that easy. I need the location of the buffer and the current offset inside the buffer. The one global variable would have pointed to a struct containing all that info.
OK, good point.
So far our dedicated addresses are these: page 0 -- for vm86 page 1 -- for vm86 0x88000 -- 0x8ffff -- stack. (stack should probably move to 0x98000) Then put log buffer at 0x90000?
The log buffer has to be on the stack during CAR. That's not a big problem because we can allocate it in stage1_main(). The problem is that we need a way to locate where exactly the buffer is.
Regards, Carl-Daniel
* Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [080204 17:42]:
It's not that easy. I need the location of the buffer and the current offset inside the buffer. The one global variable would have pointed to a struct containing all that info.
You want that pointer persistant anyways, because you will likely have to pass it to linux, too. So why not have the first 4 byte of the buffer as "buffer pointer"?
Stefan
On 04.02.2008 17:49, Stefan Reinauer wrote:
- Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [080204 17:42]:
It's not that easy. I need the location of the buffer and the current offset inside the buffer. The one global variable would have pointed to a struct containing all that info.
You want that pointer persistant anyways, because you will likely have to pass it to linux, too. So why not have the first 4 byte of the buffer as "buffer pointer"?
Hm yes. That still leaves us with the problem to locate the buffer. We cannot rely on gcc to place it on stack in the location we want.
Regards, Carl-Daniel
* Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [080204 18:09]:
Hm yes. That still leaves us with the problem to locate the buffer. We cannot rely on gcc to place it on stack in the location we want.
But we know which "memory area" is CARed. We can just use a piece of that area. No need to involve gcc and its stack
I think we're making this too hard.
Given a CAR address space, starting at CARBASE and ending at CAREND, we partition it as follows: bottom 1/2: stack top 1/2: defined by the Linux log buffer struct.
All done.
ron
On 04.02.2008 19:46, ron minnich wrote:
I think we're making this too hard.
Given a CAR address space, starting at CARBASE and ending at CAREND, we partition it as follows: bottom 1/2: stack top 1/2: defined by the Linux log buffer struct.
Are you using "top" and "bottom" in the sense of memory addresses or their place on the stack?
All done.
Generally speaking, the concept is intriguing. However, I fear we want to increase log buffer size once RAM is enabled. For targets with 4k of CAR, that means we restrict the buffer to 2k and the stack to 2k. While this may be sufficient during CAR stage, once RAM is enabled we may have deep call chains which eat more than 2k (total) of stack, which will cause silent stack corruption when the log buffer reaches its wraparound point. If we push a pointer to the log buffer struct as first element on the stack, we can move the log buffer easily once RAM is enabled, while at the same time making sure nothing will interfere with the regular stack.
Regards, Carl-Daniel
On Feb 4, 2008 11:40 AM, Carl-Daniel Hailfinger < c-d.hailfinger.devel.2006@gmx.net> wrote:
Are you using "top" and "bottom" in the sense of memory addresses or their place on the stack?
memory addresses.So for example log buf could be 0x8c000 to 0x8ffff and stack from 0x80000 to 0x8bfff
ron
On 04.02.2008 17:12, ron minnich wrote:
So, this is an example of the reason for the (void *) param I was suggesting some time back. Such needs come up.
One option is to have a convention that globals are at the base of the stack, rounded to 64k.
e.g. %esp & 0xffff0000 is where globals live.
That could work, although in a slightly different way. I would store a pointer at the base of the stack. That pointer would point to a struct which has all global info.
Regards, Carl-Daniel
On Feb 4, 2008 8:47 AM, Carl-Daniel Hailfinger < c-d.hailfinger.devel.2006@gmx.net> wrote:
That could work, although in a slightly different way. I would store a pointer at the base of the stack. That pointer would point to a struct which has all global info.
sure. At that point it's actually a parameter by any other name but :-)
ron