Petr Stehlik dixit:
>Thorsten Glaser píše v Ne 13. 01. 2013 v 21:37 +0000:
>> >Could you show me the source code of nfimvirt, please? Seems like it
>>
>> I attached it.
>
>Thanks
Actually, the attached version is v2, which doesn’t endlessly
loop in the SIGILL handler on “real hardware” any more… but I
guess it’s obsolete anyway, if the spec is “incorrect” ☹
bye,
//mirabilos
--
I want one of these. They cost 720 € though… good they don’t have the HD hole,
which indicates 3½″ floppies with double capacity… still. A tad too much, atm.
‣ http://www.floppytable.com/floppytable-images-1.html
#include <sys/types.h>
#include <sys/mman.h>
#include <err.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>
#ifndef __GNUC__
#error This file makes use of GNU C extensions.
#endif
extern long nf_get_id_asm(const char *feature_name)
asm("nf_get_id_asm")
__attribute__((__cdecl__, __regparm__(0)));
extern long nf_call_asm(unsigned long feature_id, ...)
asm("nf_call_asm")
__attribute__((__cdecl__, __regparm__(0)));
volatile sig_atomic_t got_sigill;
void sigill_handler(int sigraised, siginfo_t *info, void *context);
long nf_get_id(const char *feature_name);
#define nf_call2(id, subid, ...) __extension__({ \
long nf_call2_res; \
unsigned long nf_call2_fid; \
\
if (got_sigill) \
errx(2, "nf_call2: previous unhandled SIGILL"); \
nf_call2_fid = (unsigned long)(id) | (unsigned long)(subid); \
nf_call2_res = nf_call_asm(nf_call2_fid, ## __VA_ARGS__); \
if (got_sigill) \
errx(2, "nf_call2: SIGILL for %08lX", nf_call2_fid); \
(nf_call2_res); \
})
#ifdef __KLIBC__
void err(int, const char *, ...)
__attribute__((__noreturn__, __format__(__printf__, 2, 3)));
void errx(int, const char *, ...)
__attribute__((__noreturn__, __format__(__printf__, 2, 3)));
#endif
int
main(void)
{
long NF_NAME, NF_VERSION, sres;
char *buf;
unsigned long bufsz = 0, ures;
int pgsz;
struct sigaction sact;
if ((pgsz = getpagesize()) <= 0 || pgsz > 0x10000000)
err(2, "getpagesize() returned %d", pgsz);
while (bufsz < 4096)
bufsz += pgsz;
if ((buf = mmap(NULL, (size_t)bufsz, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, 0, (off_t)0)) == MAP_FAILED)
err(2, "mmap() %lu bytes failed", bufsz);
if (mlock(buf, bufsz))
err(2, "mlock() failed");
sigemptyset(&sact.sa_mask);
sact.sa_flags = SA_SIGINFO;
sact.sa_sigaction = sigill_handler;
got_sigill = 0;
if (sigaction(SIGILL, &sact, NULL))
err(2, "cannot install SIGILL handler");
if ((NF_NAME = nf_get_id("NF_NAME")) == -1L) {
printf("Physical (no NatFeat)\n");
return (0);
}
if ((NF_VERSION = nf_get_id("NF_VERSION")) == -1L) {
printf("Ambiguous (broken NatFeat)\n");
return (1);
}
sres = nf_call2(NF_VERSION, 0);
ures = nf_call2(NF_NAME, 0, buf, bufsz);
buf[bufsz - 1] = 0;
printf("NatFeat v%d.%d (Emulator%s: %s)", (int)((sres >> 16) & 0xFFFF),
(int)(sres & 0xFFFF), ures >= bufsz ? " (truncated)" : "", buf);
ures = nf_call2(NF_NAME, 1, buf, bufsz);
buf[bufsz - 1] = 0;
printf(" on%s: %s\n", ures >= bufsz ? " (truncated)" : "", buf);
/* munlock, munmap, signal */
return (0);
}
long
nf_get_id(const char *feature_name)
{
long res;
if (got_sigill)
errx(2, "nf_get_id: previous unhandled SIGILL");
res = nf_get_id_asm(feature_name);
if (got_sigill) {
got_sigill = 0;
return (-1L);
}
return (res & 0xFFF00000);
}
void
sigill_handler(int sigraised __attribute__((__unused__)),
siginfo_t *info __attribute__((__unused__)), void *context)
{
ucontext_t *ctx = context;
unsigned char *cp;
cp = (void *)(ctx->uc_mcontext.gregs[R_PC]);
/*
* 0x4AFC is a regular undefined opcode (for testing);
* 0x7300 and 0x7301 are our NatFeat call opcodes
*/
if (cp[0] == 0x73 && (cp[1] == 0x00 || cp[1] == 0x01)) {
ctx->uc_mcontext.gregs[R_PC] += 2;
} else {
/* SIGILL from something else */
/* bail out (longjmp) to error handler is right to do */
write(2, "E: SIGILL from something else\n", 30);
_exit(2);
}
got_sigill = 1;
}