[LinuxBIOS] 64bit issues was: [PATCH] LBv3: fix printk format warnings
c-d.hailfinger.devel.2006 at gmx.net
Mon Aug 13 05:04:45 CEST 2007
Please read through the whole mail. The first part is about printf
issues, while the second part points out much more important problems
with 64bit resources and stuff. Thanks.
On 10.08.2007 18:31, ron minnich wrote:
> Thanks very much for this.
I have another patch pending which changes %Lx (L is unspecified for
integers, happens to work) to %llx ("official" long long for integers).
Quoting from the printf(3) man page:
The length modifier
Here, `integer conversion' stands for d, i, o, u, x, or X conversion.
hh A following integer conversion corresponds to a signed
char or unsigned char argument, or a following n conversion corresponds
to a pointer to a signed char argument.
h A following integer conversion corresponds to a short int
or unsigned short int argument, or a following n conversion corresponds
to a pointer to a short int argument.
l (ell) A following integer conversion corresponds to a
long int or unsigned long int argument.
ll (ell-ell). A following integer conversion corresponds to
a long long int or unsigned long long int argument.
L A following a, A, e, E, f, F, g, or G conversion
corresponds to a long double argument.
z A following integer conversion corresponds to a size_t or
t A following integer conversion corresponds to a ptrdiff_t
* "L" is for floats only.
* "t" or "z" might be handy for resource sizes.
* "h" and "hh" for u16 and u8 seem to be unknown to most coders (except
in util/dtc) and gcc doesn't warn about them. Should investigate
usefulness for us.
> I have a suggestion. Nowadays, for things that are pointers,
> even if they are not typed as such, I've taken to this style:
> On 8/9/07, Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net> wrote:
>> +printk(BIOS_SPEW, "base = 0x%04lx, reg = 0x%02x, value = 0x%02x\r\n", base, reg,value);
> vv vvvvvvv
> printk(BIOS_SPEW, "base = %p, reg = 0x%02x, value = 0x%02x\r\n", (void *) base, reg,value);
>> + printk(BIOS_DEBUG, "ROM address for %s = %lx\n", dev_path(dev), rom_address);
> vv vvvvvvvv
> printk(BIOS_DEBUG, "ROM address for %s = %p\n", dev_path(dev), (void *) rom_address);
Do I understand this correctly? (void *) conversion and usage of %p for
things that are essentially pointers.
> Why do this? It's actually more portable, even across plan 9 and
> linux. It will probably work correctly in 64 bit mode. And, that
> rom_address really *is* an address.
I like it, but... in the first example it seems this was an error, the
base is not an address, but some u16 value.
Stefan? Can you tell us what the reason is?
The second example is more correct, but we still face a problem:
resource_t is u64 and as long as we don't use long mode, %p will expect
32bit values. However, almost everything being a resource_t (base, size,
limit) is essentially a pointer of a pointerdiff. Now how do we handle that?
And while we're at correct typing, shouldn't arch/x86/linuxbios_table.c
use resource_t in most places where it uses u64?
I have a lot of open questions:
* How do we handle accesses to resources above 4 GB when we confine
ourselves to 32bit code?
* How do 32bit operating systems handle resources above 4 GB? Should we
just avoid locating resources up there? Only do it if unavoidable?
Consider a machine with 4 GB of RAM and a graphics card with 512 MB.
That combination can be bought today. Now what will happen if video RAM
grows to 4 GB? Can we boot such a machine in 32bit mode at all? Should
we show a warning? Refuse to boot any non-64bit OS?
* Should we have some preference setting which controls 64bit resource
* Is there any point trying to handle 64bit resources on 32bit machines?
* Do we have to compile 64bit code for 64bit machines?
More information about the coreboot