shutdown
12-07-2008, 16:52
Hallo,
ich vermute, einen Bug im Linux Kernel gefunden zu haben, da ich mit C allerdings noch nicht viel Erfahrung habe, will ich das hier erstmal bestätigen lassen.
Hier erstmal mein Programm, mit dem ich teste:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
void cpuid(int *a, int *b, int *c, int *d)
{
asm volatile (" mov %4, %%eax;"
" mov %5, %%ecx;"
" cpuid;"
" mov %%eax, %0;"
" mov %%ebx, %1;"
" mov %%ecx, %2;"
" mov %%edx, %3;"
/* Output */ : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
/* Input */ : "a" (*a), "c" (*c)
/* Clobbered */ : "cc");
}
int cpuidx(int *ra, int *rb, int *rc, int *rd)
{
int fd;
char cpuid_filename[64];
int cpu=0;
uint32_t data[4];
uint32_t adr[2];
uint64_t address;
adr[0]=*ra;
adr[1]=*rc;
if ( *ra != 4 ) *rc=0;
memcpy(&address,adr,8);
//address=adr[0];
//printf("%X\n",address);
sprintf(cpuid_filename, "/dev/cpu/%d/cpuid", cpu);
if ( (fd = open(cpuid_filename, O_RDONLY)) < 0 )
{
printf("Error opening %s errno=%d (%s)\n", cpuid_filename, errno, strerror(errno));
return errno;
}
lseek(fd, address, SEEK_SET);
read(fd, &data, 16);
close(fd);
*ra=data[0];
*rb=data[1];
*rc=data[2];
*rd=data[3];
return 0;
}
int main()
{
int a=0,b=0,c=0,d=0;
a=0x80000000;
cpuid(&a,&b,&c,&d);
printf("%X %X %X %X\n",a,b,c,d);
a=0x80000000;
cpuidx(&a,&b,&c,&d);
printf("%X %X %X %X\n",a,b,c,d);
return 0;
}
Ist ein umgebauter Ausschnitt aus einem anderen Programm, sieht deswegen so unordentlich aus.
Sinn und Zweck des ganzen ist es, die CPUID-Instruktion zu nutzen, um Daten über die CPU zu Erfahren.
Hier nun der Output auf meinem System:
# ./test
80000008 0 0 0
80000008 0 0 0
Sieht wie erwartet aus, das /dev/cpu/0/cpuid-Interface und die cpuid-Instruktion liefern beide die selben Daten.
Hier nun die Ausgaben von einem Xeon, auf dem mein ursprüngliches Programm plötzlich gesponnen hat:
# ./test
80000004 0 0 0
B7F50FF4 B7F514F8 1 BFF4F140
Eindeutig ist die Ausgabe des Interfaces vom Linux-Kernel totaler Müll, die cpuid-Instruktion liefert gänzlich andere (und offensichtlich richtige) Daten.
Habe ich einen Bug im Programm oder liegt es am Betriebssystem???
ich vermute, einen Bug im Linux Kernel gefunden zu haben, da ich mit C allerdings noch nicht viel Erfahrung habe, will ich das hier erstmal bestätigen lassen.
Hier erstmal mein Programm, mit dem ich teste:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
void cpuid(int *a, int *b, int *c, int *d)
{
asm volatile (" mov %4, %%eax;"
" mov %5, %%ecx;"
" cpuid;"
" mov %%eax, %0;"
" mov %%ebx, %1;"
" mov %%ecx, %2;"
" mov %%edx, %3;"
/* Output */ : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
/* Input */ : "a" (*a), "c" (*c)
/* Clobbered */ : "cc");
}
int cpuidx(int *ra, int *rb, int *rc, int *rd)
{
int fd;
char cpuid_filename[64];
int cpu=0;
uint32_t data[4];
uint32_t adr[2];
uint64_t address;
adr[0]=*ra;
adr[1]=*rc;
if ( *ra != 4 ) *rc=0;
memcpy(&address,adr,8);
//address=adr[0];
//printf("%X\n",address);
sprintf(cpuid_filename, "/dev/cpu/%d/cpuid", cpu);
if ( (fd = open(cpuid_filename, O_RDONLY)) < 0 )
{
printf("Error opening %s errno=%d (%s)\n", cpuid_filename, errno, strerror(errno));
return errno;
}
lseek(fd, address, SEEK_SET);
read(fd, &data, 16);
close(fd);
*ra=data[0];
*rb=data[1];
*rc=data[2];
*rd=data[3];
return 0;
}
int main()
{
int a=0,b=0,c=0,d=0;
a=0x80000000;
cpuid(&a,&b,&c,&d);
printf("%X %X %X %X\n",a,b,c,d);
a=0x80000000;
cpuidx(&a,&b,&c,&d);
printf("%X %X %X %X\n",a,b,c,d);
return 0;
}
Ist ein umgebauter Ausschnitt aus einem anderen Programm, sieht deswegen so unordentlich aus.
Sinn und Zweck des ganzen ist es, die CPUID-Instruktion zu nutzen, um Daten über die CPU zu Erfahren.
Hier nun der Output auf meinem System:
# ./test
80000008 0 0 0
80000008 0 0 0
Sieht wie erwartet aus, das /dev/cpu/0/cpuid-Interface und die cpuid-Instruktion liefern beide die selben Daten.
Hier nun die Ausgaben von einem Xeon, auf dem mein ursprüngliches Programm plötzlich gesponnen hat:
# ./test
80000004 0 0 0
B7F50FF4 B7F514F8 1 BFF4F140
Eindeutig ist die Ausgabe des Interfaces vom Linux-Kernel totaler Müll, die cpuid-Instruktion liefert gänzlich andere (und offensichtlich richtige) Daten.
Habe ich einen Bug im Programm oder liegt es am Betriebssystem???