* 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.