From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1NWbbW-0005x8-Fy for mharc-grub-devel@gnu.org; Sun, 17 Jan 2010 15:20:10 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NWbbT-0005wN-48 for grub-devel@gnu.org; Sun, 17 Jan 2010 15:20:07 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NWbbO-0005wB-CO for grub-devel@gnu.org; Sun, 17 Jan 2010 15:20:06 -0500 Received: from [199.232.76.173] (port=36022 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NWbbO-0005w8-5T for grub-devel@gnu.org; Sun, 17 Jan 2010 15:20:02 -0500 Received: from fg-out-1718.google.com ([72.14.220.155]:42732) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NWbbL-0000vA-OY for grub-devel@gnu.org; Sun, 17 Jan 2010 15:20:01 -0500 Received: by fg-out-1718.google.com with SMTP id 19so186847fgg.12 for ; Sun, 17 Jan 2010 12:19:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:references:in-reply-to :x-enigmail-version:content-type; bh=MnYyYkB0sQns9p3vwM/oEgAobS2b4DV5EfibTdQwFF8=; b=FGIe54t73InGCIlJems63AoBo9XSCPB2CN2P1eloDN61kj6s4/8kQph5BUSb2KUEh9 fz4zLeQuGFnTN1YOUG9wsepNCkDz0akG6mjtepu4CyYT/DZc/MH0uzTf0jJQSDlSCUWb FnllZuen2QQhhwcE0ypBBSjOyzm+bXg7KMmek= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:x-enigmail-version:content-type; b=xUn+ShRGCA8i/7iZPnU2KxCAtjctBlBCchCPB11I5ps7Je8s4v96mFfRV13XUVja33 4VY48PbsDbOdU1POzRmbrYiCYfWhdogLmfFirjq2k6v3zJ+/O2iSpbMXU0W/Wd1nEC62 9D1+aWZ913LuyUnrqyRhwSe9h3UJKjvISeGcc= Received: by 10.87.73.33 with SMTP id a33mr6419657fgl.26.1263759597667; Sun, 17 Jan 2010 12:19:57 -0800 (PST) Received: from debian.bg45.phnet (144-116.203-62.cust.bluewin.ch [62.203.116.144]) by mx.google.com with ESMTPS id l12sm12946397fgb.5.2010.01.17.12.19.53 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 17 Jan 2010 12:19:55 -0800 (PST) Message-ID: <4B5370E3.6020202@gmail.com> Date: Sun, 17 Jan 2010 21:19:47 +0100 From: =?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?= User-Agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109) MIME-Version: 1.0 To: The development of GNU GRUB References: <4B3C98EE.8020003@gmail.com> <20100101124730.GR3692@thorin> In-Reply-To: <20100101124730.GR3692@thorin> X-Enigmail-Version: 0.95.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enigA9A44086B35C4E8FB0036F51" X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: Re: [PATCH] Proof of concept interrupt wrapping X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Jan 2010 20:20:07 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigA9A44086B35C4E8FB0036F51 Content-Type: multipart/mixed; boundary="------------090600060203070808060900" This is a multi-part message in MIME format. --------------090600060203070808060900 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Robert Millan wrote: > On Thu, Dec 31, 2009 at 01:28:30PM +0100, Vladimir '=CF=86-coder/phcode= r' Serbinenko wrote: > =20 >> Hello. We were discussing with Robert how to move BIOS interrupt >> routines out of kernel. There are following possibilities: >> 1) Have a .lowmem section in every concerned module which will always = be >> placed in low memory. Currently in experimental. >> Advantages: >> a) moving functions to modules is straightforward >> b) functions grow neither in size nor in complexity >> Disadvantages: >> c) needs lowmem allocators in core >> 2) Make every function needing bios interrupts setup its own trampolin= e. >> Due to complexity of trampolines it's not a real option >> 3) Have an universal routine grub_interrupt (int intno, struct >> grub_cpu_interrupt_regs *regs) which will be used by C routine to do t= he >> interrupt calls. This would move the complexity from asm to C. >> Advantages: >> a) simplicity in core >> b) complexity moved to a more readable language >> c) we can also rename grub_interrupt to grub_interrupt_real and make >> grub_interrupt dprintf registers before and after the call. This would= >> make debugging BIOS quirks easier. >> Disadvantages: >> a) Moving functions needs effort >> b) C functions are probably bigger but it may be offset by possibility= >> of inlining functions >> c) repeadetly changing from/to real mode is an overhead when executing= >> multiple interrupts in series. Fortunately this condition is rare in o= ur >> codebase and is only on non performance-critical parts like halting. >> d) Some functions aren't covered by this. At least grub_pxe_call is in= >> this case. But we can use method 2 for them >> =20 > > We could diminish #1.c with ifdef GRUB_MACHINE_PCBIOS, but it's still u= gly. > I like #3 a lot more. > > As for C being bigger than asm, it's argueable, taking into account tha= t > we have regparm, function alignment hacks, and gcc size optimizations := -) > > In any case #3 looks a lot cleaner. > > Some comments about the patch: > > =20 >> +struct grub_cpu_int_registers >> +{ >> + grub_uint16_t bx; >> + grub_uint16_t es; >> + grub_uint16_t cx; >> + grub_uint16_t ax; >> + grub_uint16_t dx; >> + grub_uint16_t ds; >> + grub_uint16_t di; >> + grub_uint16_t flags; >> + grub_uint16_t si; >> +}; >> =20 > > This structure is named in generic way, but its member names are CPU-sp= ecific. > Is it useful to make this generic? In practice, it will be impossible = for > CPU-independant code to use it. > =20 I changed it to _bios_ > I think it would be better to admit that this is a pure ad-hoc kludge. = It's > not beautiful, but it's *much* better than what we have now. > > =20 I added 32-bit register support since it's needed for APM. Can wrapper be merged to mainline or is it better for it to be in a separate branch and be merged with first bunch of BIOS code going out of kernel? --=20 Regards Vladimir '=CF=86-coder/phcoder' Serbinenko --------------090600060203070808060900 Content-Type: text/x-diff; name="intwrap.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="intwrap.diff" =3D=3D=3D modified file 'conf/i386-pc.rmk' --- conf/i386-pc.rmk 2010-01-15 20:11:51 +0000 +++ conf/i386-pc.rmk 2010-01-17 20:16:27 +0000 @@ -64,7 +64,7 @@ partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \= machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \ machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \ - machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h i1= 8n.h + machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h i1= 8n.h machine/int.h kernel_img_CFLAGS =3D $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS) kernel_img_ASFLAGS =3D $(COMMON_ASFLAGS) kernel_img_LDFLAGS =3D $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KER= NEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS) =3D=3D=3D modified file 'disk/i386/pc/biosdisk.c' --- disk/i386/pc/biosdisk.c 2010-01-04 23:30:27 +0000 +++ disk/i386/pc/biosdisk.c 2010-01-17 20:16:27 +0000 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,59 @@ #include =20 static int cd_drive =3D 0; +static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *d= ap); + +static int grub_biosdisk_get_num_floppies (void) +{ + struct grub_bios_int_registers regs; + int drive; + + /* reset the disk system first */ + regs.eax =3D 0; + regs.edx =3D 0; + regs.flags =3D GRUB_CPU_INT_FLAGS_DEFAULT; + + grub_bios_interrupt (0x13, ®s); + + for (drive =3D 0; drive < 2; drive++) + { + regs.flags =3D GRUB_CPU_INT_FLAGS_DEFAULT | GRUB_CPU_INT_FLAGS_CAR= RY; + regs.edx =3D drive; + + /* call GET DISK TYPE */ + regs.eax =3D 0x1500; + grub_bios_interrupt (0x13, ®s); + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + break; + + /* check if this drive exists */ + if (!(regs.eax & 0x300)) + break; + } + + return drive; +} + +/* + * Call IBM/MS INT13 Extensions (int 13 %ah=3DAH) for DRIVE. DAP + * is passed for disk address packet. If an error occurs, return + * non-zero, otherwise zero. + */ + +static int=20 +grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) +{ + struct grub_bios_int_registers regs; + regs.eax =3D ah << 8; + /* compute the address of disk_address_packet */ + regs.ds =3D (((grub_addr_t) dap) & 0xffff0000) >> 4; + regs.esi =3D (((grub_addr_t) dap) & 0xffff); + regs.edx =3D drive; + regs.flags =3D GRUB_CPU_INT_FLAGS_DEFAULT; + + grub_bios_interrupt (0x13, ®s); + return (regs.eax >> 8) & 0xff; +} =20 static int grub_biosdisk_get_drive (const char *name) =3D=3D=3D modified file 'include/grub/i386/pc/biosdisk.h' --- include/grub/i386/pc/biosdisk.h 2009-06-10 21:04:23 +0000 +++ include/grub/i386/pc/biosdisk.h 2009-12-31 11:49:34 +0000 @@ -106,7 +106,6 @@ grub_uint64_t block; } __attribute__ ((packed)); =20 -int EXPORT_FUNC(grub_biosdisk_rw_int13_extensions) (int ah, int drive, v= oid *dap); int EXPORT_FUNC(grub_biosdisk_rw_standard) (int ah, int drive, int coff,= int hoff, int soff, int nsec, int segment); int EXPORT_FUNC(grub_biosdisk_check_int13_extensions) (int drive); @@ -118,7 +117,6 @@ unsigned long *cylinders, unsigned long *heads, unsigned long *sectors); -int EXPORT_FUNC(grub_biosdisk_get_num_floppies) (void); =20 void grub_biosdisk_init (void); void grub_biosdisk_fini (void); =3D=3D=3D added file 'include/grub/i386/pc/int.h' --- include/grub/i386/pc/int.h 1970-01-01 00:00:00 +0000 +++ include/grub/i386/pc/int.h 2010-01-17 19:23:55 +0000 @@ -0,0 +1,52 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_INTERRUPT_MACHINE_HEADER +#define GRUB_INTERRUPT_MACHINE_HEADER 1 + +#include + +struct grub_bios_int_registers +{ + grub_uint32_t eax; + grub_uint16_t es; + grub_uint16_t ds; + grub_uint16_t flags; + grub_uint16_t dummy; + grub_uint32_t ebx; + grub_uint32_t ecx; + grub_uint32_t edi; + grub_uint32_t esi; + grub_uint32_t edx; +}; + +#define GRUB_CPU_INT_FLAGS_CARRY 0x1 +#define GRUB_CPU_INT_FLAGS_PARITY 0x4 +#define GRUB_CPU_INT_FLAGS_ADJUST 0x10 +#define GRUB_CPU_INT_FLAGS_ZERO 0x40 +#define GRUB_CPU_INT_FLAGS_SIGN 0x80 +#define GRUB_CPU_INT_FLAGS_TRAP 0x100 +#define GRUB_CPU_INT_FLAGS_INTERRUPT 0x200 +#define GRUB_CPU_INT_FLAGS_DIRECTION 0x400 +#define GRUB_CPU_INT_FLAGS_OVERFLOW 0x800 +#define GRUB_CPU_INT_FLAGS_DEFAULT GRUB_CPU_INT_FLAGS_INTERRUPT + +void EXPORT_FUNC (grub_bios_interrupt) (grub_uint8_t intno, + struct grub_bios_int_registers *regs); + +#endif =3D=3D=3D modified file 'kern/i386/pc/startup.S' --- kern/i386/pc/startup.S 2010-01-03 22:05:07 +0000 +++ kern/i386/pc/startup.S 2010-01-17 20:16:27 +0000 @@ -567,44 +567,6 @@ #include "../loader.S" =20 /* - * int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap= ) - * - * Call IBM/MS INT13 Extensions (int 13 %ah=3DAH) for DRIVE. DAP - * is passed for disk address packet. If an error occurs, return - * non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_rw_int13_extensions) - pushl %ebp - pushl %esi - - /* compute the address of disk_address_packet */ - movw %cx, %si - xorw %cx, %cx - shrl $4, %ecx /* save the segment to cx */ - - /* ah */ - movb %al, %dh - /* enter real mode */ - call prot_to_real - - .code16 - movb %dh, %ah - movw %cx, %ds - int $0x13 /* do the operation */ - movb %ah, %dl /* save return value */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %dl, %al /* return value in %eax */ - - popl %esi - popl %ebp - - ret - -/* * int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hof= f, * int soff, int nsec, int segment) * @@ -862,43 +824,6 @@ =20 =20 /* - * int grub_biosdisk_get_num_floppies (void) - */ -FUNCTION(grub_biosdisk_get_num_floppies) - pushl %ebp - - xorl %edx, %edx - call prot_to_real - - .code16 - /* reset the disk system first */ - int $0x13 -1: - stc - - /* call GET DISK TYPE */ - movb $0x15, %ah - int $0x13 - - jc 2f - - /* check if this drive exists */ - testb $0x3, %ah - jz 2f - - incb %dl - cmpb $2, %dl - jne 1b -2: - DATA32 call real_to_prot - .code32 - - movl %edx, %eax - popl %ebp - ret - - -/* * * grub_get_memsize(i) : return the memory size in KB. i =3D=3D 0 for c= onventional * memory, i =3D=3D 1 for extended memory @@ -2142,3 +2067,97 @@ popl %esi popl %ebp ret + +FUNCTION(grub_bios_interrupt) + pushl %ebp + pushl %ecx + pushl %eax + pushl %edx +=09 + movb %al, intno + movl (%edx), %eax + movl %eax, LOCAL(bios_register_eax) + movw 4(%edx), %ax + movw %ax, LOCAL(bios_register_es) + movw 6(%edx), %ax + movw %ax, LOCAL(bios_register_ds) + movw 8(%edx), %ax + movw %ax, LOCAL(bios_register_flags) + + movl 12(%edx), %ebx + movl 16(%edx), %ecx + movl 20(%edx), %edi + movl 24(%edx), %esi + movl 28(%edx), %edx + + call prot_to_real + .code16 + + mov %ds, %ax + push %ax + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_es): + .short 0 + movw %ax, %es + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_ds): + .short 0 + movw %ax, %ds + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_flags): + .short 0 + push %ax + popf + + /* movl imm32, %eax*/ + .byte 0x66, 0xb8 +LOCAL(bios_register_eax): + .long 0 +=09 + /* int imm8. */ + .byte 0xcd +intno:=09 + .byte 0 + + movl %eax, %cs:LOCAL(bios_register_eax) + movw %ds, %ax + movw %ax, %cs:LOCAL(bios_register_ds) + pop %ax + mov %ax, %ds + pushf + pop %ax + movw %ax, LOCAL(bios_register_flags) + mov %es, %ax + movw %ax, LOCAL(bios_register_es) + + DATA32 call real_to_prot + .code32 + + popl %eax + + movl %ebx, 12(%eax) + movl %ecx, 16(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %edx, 28(%eax) + + movl %eax, %edx + + movl LOCAL(bios_register_eax), %eax + movl %eax, (%edx) + movw LOCAL(bios_register_es), %ax + movw %ax, 4(%edx) + movw LOCAL(bios_register_ds), %ax + movw %ax, 6(%edx) + movw LOCAL(bios_register_flags), %ax + movw %ax, 8(%edx) + + popl %eax + popl %ecx + popl %ebp + ret --------------090600060203070808060900-- --------------enigA9A44086B35C4E8FB0036F51 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iF4EAREKAAYFAktTcOkACgkQNak7dOguQgl1GQEApIp5zdFmFxuOJkt8WKZ0X9tR a7kez/YKOyM4mwgjByIA/iWmaSTgnG9sCtEwazAhlgojc1kD+JZKkWeGwH/3sgGY =AO2e -----END PGP SIGNATURE----- --------------enigA9A44086B35C4E8FB0036F51--