* CPUID module
@ 2007-05-18 15:50 Robert Millan
2007-05-18 18:35 ` Yoshinori K. Okuji
0 siblings, 1 reply; 4+ messages in thread
From: Robert Millan @ 2007-05-18 15:50 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 878 bytes --]
Here's a patch to implement cpuid.mod. This module checks for CPU features
(currently only the long_mode flag, but more could be added if needed) using
cpuid. The idea behind this is that grub.cfg scripts can use it to decide
wether a 64-bit or 32-bit Linux image should be boot (e.g. like Debian
multiarch CDs do). I haven't investigated what the syntax for that hack
would be, although I assume it's possible.
Cpuid detection code has been borrowed from gcc and is FSF-copyrighted.
I'm not sure where would the file go. I noticed that other utility modules
(e.g. hello/hello.c) add themselves in the top dir, so I suppose i386/cpuid.c
would be ok?
Or perhaps we could have an "util" dir for modules?
--
Robert Millan
My spam trap is honeypot@aybabtu.com. Note: this address is only intended
for spam harvesters. Writing to it will get you added to my black list.
[-- Attachment #2: cpuid.diff --]
[-- Type: text/x-diff, Size: 4677 bytes --]
2007-05-18 Robert Millan <rmh@aybabtu.com>
* i386/cpuid.c: New module.
* DISTLIST: Add it.
* conf/i386-efi.rmk: Enable cpuid.mod.
* conf/i386-pc.rmk: Likewise.
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/conf/i386-efi.rmk grub2-1.95+20070515/conf/i386-efi.rmk
--- grub2-1.95+20070515.old/conf/i386-efi.rmk 2007-05-18 13:07:26.000000000 +0200
+++ grub2-1.95+20070515/conf/i386-efi.rmk 2007-05-18 13:44:49.000000000 +0200
@@ -70,7 +70,7 @@
# Modules.
pkgdata_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
- _linux.mod linux.mod
+ _linux.mod linux.mod cpuid.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -129,4 +129,9 @@
linux_mod_CFLAGS = $(COMMON_CFLAGS)
linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For cpuid.mod.
+cpuid_mod_SOURCES = i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/conf/i386-pc.rmk grub2-1.95+20070515/conf/i386-pc.rmk
--- grub2-1.95+20070515.old/conf/i386-pc.rmk 2007-05-05 01:00:56.000000000 +0200
+++ grub2-1.95+20070515/conf/i386-pc.rmk 2007-05-18 13:41:07.000000000 +0200
@@ -120,7 +120,7 @@
pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \
vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
- videotest.mod play.mod bitmap.mod tga.mod
+ videotest.mod play.mod bitmap.mod tga.mod cpuid.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -224,4 +224,9 @@
tga_mod_CFLAGS = $(COMMON_CFLAGS)
tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For cpuid.mod.
+cpuid_mod_SOURCES = i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/DISTLIST grub2-1.95+20070515/DISTLIST
--- grub2-1.95+20070515.old/DISTLIST 2007-05-04 09:11:44.000000000 +0200
+++ grub2-1.95+20070515/DISTLIST 2007-05-18 13:37:05.000000000 +0200
@@ -81,6 +81,7 @@
fs/xfs.c
fs/hfsplus.c
hello/hello.c
+i386/cpuid.c
include/grub/acorn_filecore.h
include/grub/arg.h
include/grub/bitmap.h
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/i386/cpuid.c grub2-1.95+20070515/i386/cpuid.c
--- grub2-1.95+20070515.old/i386/cpuid.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2-1.95+20070515/i386/cpuid.c 2007-05-18 13:33:35.000000000 +0200
@@ -0,0 +1,73 @@
+/* cpuid.c - test for CPU features */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ * Based on gcc/gcc/config/i386/driver-i386.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+
+#define cpuid(num,a,b,c,d) \
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "0" (num))
+
+#define bit_LM (1 << 29)
+
+GRUB_MOD_INIT(cpuid)
+{
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int max_level;
+ unsigned int ext_level;
+ unsigned char has_longmode = 0;
+
+ /* See if we can use cpuid. */
+ asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+ "pushl %0; popfl; pushfl; popl %0; popfl"
+ : "=&r" (eax), "=&r" (ebx)
+ : "i" (0x00200000));
+ if (((eax ^ ebx) & 0x00200000) == 0)
+ goto done;
+
+ /* Check the highest input value for eax. */
+ cpuid (0, eax, ebx, ecx, edx);
+ /* We only look at the first four characters. */
+ max_level = eax;
+ if (max_level == 0)
+ goto done;
+
+ cpuid (0x80000000, eax, ebx, ecx, edx);
+ ext_level = eax;
+ if (ext_level < 0x80000000)
+ goto done;
+
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+ has_longmode = !!(edx & bit_LM);
+
+done:
+ grub_env_set ("cpuid_long_mode", has_longmode ? "1" : "0");
+}
+
+GRUB_MOD_FINI(cpuid)
+{
+ grub_env_unset ("cpuid_long_mode");
+}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: CPUID module
2007-05-18 15:50 CPUID module Robert Millan
@ 2007-05-18 18:35 ` Yoshinori K. Okuji
2007-05-19 10:55 ` Robert Millan
0 siblings, 1 reply; 4+ messages in thread
From: Yoshinori K. Okuji @ 2007-05-18 18:35 UTC (permalink / raw)
To: The development of GRUB 2
On Friday 18 May 2007 17:50, Robert Millan wrote:
> Here's a patch to implement cpuid.mod.
Great.
> This module checks for CPU features
> (currently only the long_mode flag, but more could be added if needed)
> using cpuid. The idea behind this is that grub.cfg scripts can use it to
> decide wether a 64-bit or 32-bit Linux image should be boot (e.g. like
> Debian multiarch CDs do). I haven't investigated what the syntax for that
> hack would be, although I assume it's possible.
Personally, I think it would be cleaner to just return true or false (like
test) rather than setting an environment variable. For instance:
if cpuid --long-mode; then ...; else ...; fi
> Cpuid detection code has been borrowed from gcc and is FSF-copyrighted.
>
> I'm not sure where would the file go. I noticed that other utility modules
> (e.g. hello/hello.c) add themselves in the top dir, so I suppose
> i386/cpuid.c would be ok?
>
> Or perhaps we could have an "util" dir for modules?
No. Please use commands/i386/. "util" is strictly for utilities for an host
operating system.
Okuji
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: CPUID module
2007-05-18 18:35 ` Yoshinori K. Okuji
@ 2007-05-19 10:55 ` Robert Millan
2007-05-19 17:32 ` Yoshinori K. Okuji
0 siblings, 1 reply; 4+ messages in thread
From: Robert Millan @ 2007-05-19 10:55 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1261 bytes --]
On Fri, May 18, 2007 at 08:35:35PM +0200, Yoshinori K. Okuji wrote:
> > This module checks for CPU features
> > (currently only the long_mode flag, but more could be added if needed)
> > using cpuid. The idea behind this is that grub.cfg scripts can use it to
> > decide wether a 64-bit or 32-bit Linux image should be boot (e.g. like
> > Debian multiarch CDs do). I haven't investigated what the syntax for that
> > hack would be, although I assume it's possible.
>
> Personally, I think it would be cleaner to just return true or false (like
> test) rather than setting an environment variable. For instance:
Done.
> if cpuid --long-mode; then ...; else ...; fi
The return value ($?) is set, but this syntax doesn't work. How can this
functionality be tested?
> No. Please use commands/i386/. "util" is strictly for utilities for an host
> operating system.
Done.
Please have a look at the new patch.
2007-05-19 Robert Millan <rmh@aybabtu.com>
* commands/i386/cpuid.c: New module.
* DISTLIST: Add it.
* conf/i386-efi.rmk: Enable cpuid.mod.
* conf/i386-pc.rmk: Likewise.
--
Robert Millan
My spam trap is honeypot@aybabtu.com. Note: this address is only intended
for spam harvesters. Writing to it will get you added to my black list.
[-- Attachment #2: cpuid.diff --]
[-- Type: text/x-diff, Size: 5656 bytes --]
diff -Nur grub2-1.95+20070516.old/commands/i386/cpuid.c grub2-1.95+20070516/commands/i386/cpuid.c
--- grub2-1.95+20070516.old/commands/i386/cpuid.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2-1.95+20070516/commands/i386/cpuid.c 2007-05-19 12:49:45.000000000 +0200
@@ -0,0 +1,94 @@
+/* cpuid.c - test for CPU features */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ * Based on gcc/gcc/config/i386/driver-i386.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+
+#define cpuid(num,a,b,c,d) \
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "0" (num))
+
+#define bit_LM (1 << 29)
+
+unsigned char has_longmode = 0;
+
+static const struct grub_arg_option options[] =
+ {
+ {"long-mode", 'l', 0, "check for long mode flag (default)", 0, 0},
+ {0, 0, 0, 0, 0, 0}
+ };
+
+static grub_err_t
+grub_cmd_cpuid (struct grub_arg_list *state __attribute__ ((unused)), int argc,
+ char **args)
+
+{
+ return !has_longmode;
+}
+
+GRUB_MOD_INIT(cpuid)
+{
+#ifdef __x86_64__
+ /* grub-emu */
+ has_longmode = 1;
+#else
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int max_level;
+ unsigned int ext_level;
+
+ /* See if we can use cpuid. */
+ asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+ "pushl %0; popfl; pushfl; popl %0; popfl"
+ : "=&r" (eax), "=&r" (ebx)
+ : "i" (0x00200000));
+ if (((eax ^ ebx) & 0x00200000) == 0)
+ goto done;
+
+ /* Check the highest input value for eax. */
+ cpuid (0, eax, ebx, ecx, edx);
+ /* We only look at the first four characters. */
+ max_level = eax;
+ if (max_level == 0)
+ goto done;
+
+ cpuid (0x80000000, eax, ebx, ecx, edx);
+ ext_level = eax;
+ if (ext_level < 0x80000000)
+ goto done;
+
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+ has_longmode = !!(edx & bit_LM);
+done:
+#endif
+
+ grub_register_command ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_CMDLINE,
+ "cpuid", "Check for CPU features", options);
+}
+
+GRUB_MOD_FINI(cpuid)
+{
+ grub_unregister_command ("cpuid");
+}
diff -Nur grub2-1.95+20070516.old/conf/i386-efi.rmk grub2-1.95+20070516/conf/i386-efi.rmk
--- grub2-1.95+20070516.old/conf/i386-efi.rmk 2007-05-16 17:05:00.000000000 +0200
+++ grub2-1.95+20070516/conf/i386-efi.rmk 2007-05-19 11:46:29.000000000 +0200
@@ -43,6 +43,7 @@
commands/terminal.c commands/ls.c commands/test.c \
commands/search.c \
commands/i386/pc/halt.c commands/i386/pc/reboot.c \
+ commands/i386/cpuid.c \
disk/loopback.c \
fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \
fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \
@@ -71,7 +72,7 @@
# Modules.
pkgdata_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
- _linux.mod linux.mod
+ _linux.mod linux.mod cpuid.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -130,4 +131,9 @@
linux_mod_CFLAGS = $(COMMON_CFLAGS)
linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For cpuid.mod.
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff -Nur grub2-1.95+20070516.old/conf/i386-pc.rmk grub2-1.95+20070516/conf/i386-pc.rmk
--- grub2-1.95+20070516.old/conf/i386-pc.rmk 2007-05-16 17:19:38.000000000 +0200
+++ grub2-1.95+20070516/conf/i386-pc.rmk 2007-05-19 11:46:19.000000000 +0200
@@ -90,6 +90,7 @@
commands/terminal.c commands/ls.c commands/test.c \
commands/search.c commands/blocklist.c \
commands/i386/pc/halt.c commands/i386/pc/reboot.c \
+ commands/i386/cpuid.c \
disk/loopback.c disk/raid.c disk/lvm.c \
fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \
fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \
@@ -120,7 +121,7 @@
pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \
vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
- videotest.mod play.mod bitmap.mod tga.mod
+ videotest.mod play.mod bitmap.mod tga.mod cpuid.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -224,4 +225,9 @@
tga_mod_CFLAGS = $(COMMON_CFLAGS)
tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For cpuid.mod.
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff -Nur grub2-1.95+20070516.old/DISTLIST grub2-1.95+20070516/DISTLIST
--- grub2-1.95+20070516.old/DISTLIST 2007-05-16 17:19:37.000000000 +0200
+++ grub2-1.95+20070516/DISTLIST 2007-05-19 11:45:13.000000000 +0200
@@ -43,6 +43,7 @@
commands/terminal.c
commands/test.c
commands/videotest.c
+commands/i386/cpuid.c
commands/i386/pc/halt.c
commands/i386/pc/play.c
commands/i386/pc/reboot.c
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: CPUID module
2007-05-19 10:55 ` Robert Millan
@ 2007-05-19 17:32 ` Yoshinori K. Okuji
0 siblings, 0 replies; 4+ messages in thread
From: Yoshinori K. Okuji @ 2007-05-19 17:32 UTC (permalink / raw)
To: The development of GRUB 2
On Saturday 19 May 2007 12:55, Robert Millan wrote:
> > if cpuid --long-mode; then ...; else ...; fi
>
> The return value ($?) is set, but this syntax doesn't work. How can this
> functionality be tested?
Sorry, I am not sure. :(
Possibly, not all planned features are implemented in the scripting engine...
> Please have a look at the new patch.
Looks good to me.
Thanks,
Okuji
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-05-19 17:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-18 15:50 CPUID module Robert Millan
2007-05-18 18:35 ` Yoshinori K. Okuji
2007-05-19 10:55 ` Robert Millan
2007-05-19 17:32 ` Yoshinori K. Okuji
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.