blob: 1aaa3eeb204a1976364e28bc756a6d56b11a7aac [file] [log] [blame]
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
* Portions Copyright (c) 2000 Ulrich Drepper
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
*/
/* $Id: fork05.c,v 1.4 2001/02/28 17:42:00 nstraz Exp $ */
/**********************************************************
*
* Linux Test Project - Silicon Graphics, Inc.
*
* TEST IDENTIFIER : fork05
*
* EXECUTED BY : anyone
*
* TEST TITLE : Make sure LDT is propagated correctly
*
* TEST CASE TOTAL : 1
*
* CPU TYPES : i386
*
* AUTHORS : Ulrich Drepper
* Nate Straz
*
*On Sat, Aug 12, 2000 at 12:47:31PM -0700, Ulrich Drepper wrote:
*> Ever since the %gs handling was fixed in the 2.3.99 series the
*> appended test program worked. Now with 2.4.0-test6 it's not working
*> again. Looking briefly over the patch from test5 to test6 I haven't
*> seen an immediate candidate for the breakage. It could be missing
*> propagation of the LDT to the new process (and therefore an invalid
*> segment descriptor) or simply clearing %gs.
*>
*> Anyway, this is what you should see and what you get with test5:
*>
*> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*> a = 42
*> %gs = 0x0007
*> %gs = 0x0007
*> a = 99
*> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*>
*> This is what you get with test6:
*>
*> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*> a = 42
*> %gs = 0x0007
*> %gs = 0x0000
*> <SEGFAULT>
*> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*>
*> If somebody is actually creating a test suite for the kernel, please
*> add this program. It's mostly self-contained. The correct handling
*> of %gs is really important since glibc 2.2 will make heavy use of it.
*>
*> - --
*> - ---------------. ,-. 1325 Chesapeake Terrace
*> Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA
*> Red Hat `--' drepper at redhat.com `------------------------
*>
*> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*
*********************************************************/
#include <stdio.h>
#if defined(linux) && defined(__i386__)
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
struct modify_ldt_ldt_s
{
unsigned int entry_number;
unsigned long int base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
unsigned int empty:25;
};
void modify_ldt(int, struct modify_ldt_ldt_s *, int);
asm(" .type modify_ldt,@function
modify_ldt:
push %ebx
mov 0x10(%esp,1),%edx
mov 0xc(%esp,1),%ecx
mov 0x8(%esp,1),%ebx
mov $0x7b,%eax
int $0x80
pop %ebx
ret");
int a = 42;
int
main ()
{
struct modify_ldt_ldt_s ldt0;
int lo;
pid_t pid;
int res;
ldt0.entry_number = 0;
ldt0.base_addr = (long) &a;
ldt0.limit = 4;
ldt0.seg_32bit = 1;
ldt0.contents = 0;
ldt0.read_exec_only = 0;
ldt0.limit_in_pages = 0;
ldt0.seg_not_present = 0;
ldt0.useable = 1;
ldt0.empty = 0;
modify_ldt (1, &ldt0, sizeof (ldt0));
asm ("movw %w0, %%gs" : : "q" (7));
asm ("movl %%gs:0, %0" : "=r" (lo));
printf ("a = %d\n", lo);
asm ("pushl %%gs; popl %0" : "=q" (lo));
printf ("%%gs = %#06hx\n", lo);
asm ("movl %0, %%gs:0" : : "r" (99));
pid = fork ();
if (pid == 0) {
asm ("pushl %%gs; popl %0" : "=q" (lo));
printf ("%%gs = %#06hx\n", lo);
asm ("movl %%gs:0, %0" : "=r" (lo));
printf ("a = %d\n", lo);
exit (lo != 99);
} else {
waitpid (pid, &res, 0);
}
return WIFSIGNALED(res);
}
#else /* if defined(linux) && defined(__i386__) */
int
main()
{
printf("%%gs test only for ix86\n");
/*
* should be successful on all non-ix86 platforms.
*/
return(0);
}
#endif /* if defined(linux) && defined(__i386__) */