Message ID | 1275678883-7082-16-git-send-email-rth@twiddle.net |
---|---|
State | New |
Headers | show |
On Fri, Jun 04, 2010 at 12:14:23PM -0700, Richard Henderson wrote: > Verify that we have all the instruction extensions that we generate. > Future patches can tailor code generation to the set of instructions > that are present. > > Signed-off-by: Richard Henderson <rth@twiddle.net> > --- > tcg/s390/tcg-target.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 113 insertions(+), 0 deletions(-) > > diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c > index 3944cb1..d99bb5c 100644 > --- a/tcg/s390/tcg-target.c > +++ b/tcg/s390/tcg-target.c > @@ -229,6 +229,17 @@ static void *qemu_st_helpers[4] = { > > static uint8_t *tb_ret_addr; > > +/* A list of relevant facilities used by this translator. Some of these > + are required for proper operation, and these are checked at startup. */ > + > +#define FACILITY_ZARCH (1ULL << (63 - 1)) > +#define FACILITY_ZARCH_ACTIVE (1ULL << (63 - 2)) > +#define FACILITY_LONG_DISP (1ULL << (63 - 18)) > +#define FACILITY_EXT_IMM (1ULL << (63 - 21)) > +#define FACILITY_GEN_INST_EXT (1ULL << (63 - 34)) > + > +static uint64_t facilities; > + > static void patch_reloc(uint8_t *code_ptr, int type, > tcg_target_long value, tcg_target_long addend) > { > @@ -1177,6 +1188,106 @@ static const TCGTargetOpDef s390_op_defs[] = { > { -1 }, > }; > > +/* ??? Linux kernels provide an AUXV entry AT_HWCAP that provides most of > + this information. However, getting at that entry is not easy this far > + away from main. Our options are: start searching from environ, but > + that fails as soon as someone does a setenv in between. Read the data > + from /proc/self/auxv. Or do the probing ourselves. The only thing > + extra that AT_HWCAP gives us is HWCAP_S390_HIGH_GPRS, which indicates > + that the kernel saves all 64-bits of the registers around traps while > + in 31-bit mode. But this is true of all "recent" kernels (ought to dig > + back and see from when this might not be true). */ > + > +#include <signal.h> > + > +static volatile sig_atomic_t got_sigill; > + > +static void sigill_handler(int sig) > +{ > + got_sigill = 1; > +} > + > +static void query_facilities(void) > +{ > + struct sigaction sa_old, sa_new; > + register int r0 __asm__("0"); > + register void *r1 __asm__("1"); > + int fail; > + > + memset(&sa_new, 0, sizeof(sa_new)); > + sa_new.sa_handler = sigill_handler; > + sigaction(SIGILL, &sa_new, &sa_old); > + > + /* First, try STORE FACILITY LIST EXTENDED. If this is present, then > + we need not do any more probing. Unfortunately, this itself is an > + extension and the original STORE FACILITY LIST instruction is > + kernel-only, storing its results at absolute address 200. */ > + /* stfle 0(%r1) */ > + r1 = &facilities; > + asm volatile(".word 0xb2b0,0x1000" > + : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc"); Wouldn't it be possible to use the instruction directly instead of dumping the opcode values? Same below > + > + if (got_sigill) { > + /* STORE FACILITY EXTENDED is not available. Probe for one of each > + kind of instruction that we're interested in. */ > + /* ??? Possibly some of these are in practice never present unless > + the store-facility-extended facility is also present. But since > + that isn't documented it's just better to probe for each. */ > + > + /* Test for z/Architecture. Required even in 31-bit mode. */ > + got_sigill = 0; > + /* agr %r0,%r0 */ > + asm volatile(".word 0xb908,0x0000" : "=r"(r0) : : "cc"); > + if (!got_sigill) { > + facilities |= FACILITY_ZARCH | FACILITY_ZARCH_ACTIVE; > + } > + > + /* Test for long displacement. */ > + got_sigill = 0; > + /* ly %r0,0(%r1) */ > + r1 = &facilities; > + asm volatile(".word 0xe300,0x1000,0x0058" > + : "=r"(r0) : "r"(r1) : "cc"); > + if (!got_sigill) { > + facilities |= FACILITY_LONG_DISP; > + } > + > + /* Test for extended immediates. */ > + got_sigill = 0; > + /* afi %r0,0 */ > + asm volatile(".word 0xc209,0x0000,0x0000" : : : "cc"); > + if (!got_sigill) { > + facilities |= FACILITY_EXT_IMM; > + } > + > + /* Test for general-instructions-extension. */ > + got_sigill = 0; > + /* msfi %r0,1 */ > + asm volatile(".word 0xc201,0x0000,0x0001"); > + if (!got_sigill) { > + facilities |= FACILITY_GEN_INST_EXT; > + } > + } > + > + sigaction(SIGILL, &sa_old, NULL); > + > + /* The translator currently uses these extensions unconditionally. > + Pruning this back to the base ESA/390 architecture doesn't seem > + worthwhile, since even the KVM target requires z/Arch. */ > + fail = 0; > + if ((facilities & FACILITY_ZARCH_ACTIVE) == 0) { > + fprintf(stderr, "TCG: z/Arch facility is required\n"); > + fail = 1; > + } > + if ((facilities & FACILITY_LONG_DISP) == 0) { > + fprintf(stderr, "TCG: long-displacement facility is required\n"); > + fail = 1; > + } > + if (fail) { > + exit(-1); > + } > +} > + > void tcg_target_init(TCGContext *s) > { > #if !defined(CONFIG_USER_ONLY) > @@ -1186,6 +1297,8 @@ void tcg_target_init(TCGContext *s) > } > #endif > > + query_facilities(); > + > tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); > tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff); > > -- > 1.7.0.1 > > >
On 06/10/2010 03:28 AM, Aurelien Jarno wrote: >> + asm volatile(".word 0xb2b0,0x1000" >> + : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc"); > > Wouldn't it be possible to use the instruction directly instead of > dumping the opcode values? Same below No, they aren't recognized by older assemblers. For instance, the one shipped with RHEL 5.5, and possibly even by Debian Lenny (I don't currently have access to that machine to check). Apparently some of these are quite new insns -- 2008 era. That said, all the hardware to which either I or agraf have access are the latest z10 machines. Frankly I expect that to be true of most if not all machines, since I think it's just a microcode update which everyone with an active support contract can get. r~
On Thu, Jun 10, 2010 at 03:19:25PM -0700, Richard Henderson wrote: > On 06/10/2010 03:28 AM, Aurelien Jarno wrote: > >> + asm volatile(".word 0xb2b0,0x1000" > >> + : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc"); > > > > Wouldn't it be possible to use the instruction directly instead of > > dumping the opcode values? Same below > > No, they aren't recognized by older assemblers. For instance, the one shipped > with RHEL 5.5, and possibly even by Debian Lenny (I don't currently have access > to that machine to check). Apparently some of these are quite new insns -- 2008 era. > > That said, all the hardware to which either I or agraf have access are the latest > z10 machines. Frankly I expect that to be true of most if not all machines, since > I think it's just a microcode update which everyone with an active support contract > can get. > FYI, that's the /proc/cpuinfo of s390 machines I have (more or less) access: features : esan3 zarch msa ldisp features : esan3 zarch stfle msa ldisp eimm dfp features : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs So that's seems fine. However, looking more in details in the code again, I do wonder about this part: > + /* Test for z/Architecture. Required even in 31-bit mode. */ > + got_sigill = 0; > + /* agr %r0,%r0 */ > + asm volatile(".word 0xb908,0x0000" : "=r"(r0) : : "cc"); > + if (!got_sigill) { > + facilities |= FACILITY_ZARCH | FACILITY_ZARCH_ACTIVE; > + } > + What's the difference between FACILITY_ZARCH and FACILITY_ZARCH_ACTIVE, as both are actually flagged together. My guess is that FACILITY_ZARCH_ACTIVE is needed in 64-bit mode, why FACILITY_ZARCH is only needed for a possible future 32-bit mode. Is it correct?
On 06/11/2010 01:06 AM, Aurelien Jarno wrote: > What's the difference between FACILITY_ZARCH and FACILITY_ZARCH_ACTIVE, > as both are actually flagged together. My guess is that > FACILITY_ZARCH_ACTIVE is needed in 64-bit mode, why FACILITY_ZARCH is > only needed for a possible future 32-bit mode. Is it correct? Loosely, ZARCH is set when the system is 64-bit capable, whether or not it is active. The OS would check this bit at startup if it wanted to change modes. This bit isn't really interesting to us in userspace. ZARCH_ACTIVE is set when the system is in 64-bit mode, i.e. you've booted with a 64-bit kernel. Note that this says nothing about the address decoding mode -- this bit can be set while the PSW is set for 31-bit address translation, e.g. running a 32-bit program on a 64-bit kernel. r~
On 06/11/2010 01:06 AM, Aurelien Jarno wrote: >> That said, all the hardware to which either I or agraf have access are the latest >> z10 machines. Frankly I expect that to be true of most if not all machines, since >> I think it's just a microcode update which everyone with an active support contract >> can get. >> > > FYI, that's the /proc/cpuinfo of s390 machines I have (more or less) > access: > > features : esan3 zarch msa ldisp > features : esan3 zarch stfle msa ldisp eimm dfp > features : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs Interesting that your first one doesn't have stfle. That one will have to go through the SIGILL path. I would be very interested to have you test that code path. Also, what era is that second machine without highgprs? Is it running an old kernel, or a 32-bit kernel? r~
On Fri, Jun 11, 2010 at 06:07:52AM -0700, Richard Henderson wrote: > On 06/11/2010 01:06 AM, Aurelien Jarno wrote: > > What's the difference between FACILITY_ZARCH and FACILITY_ZARCH_ACTIVE, > > as both are actually flagged together. My guess is that > > FACILITY_ZARCH_ACTIVE is needed in 64-bit mode, why FACILITY_ZARCH is > > only needed for a possible future 32-bit mode. Is it correct? > > Loosely, > > ZARCH is set when the system is 64-bit capable, whether or not it is active. > The OS would check this bit at startup if it wanted to change modes. This > bit isn't really interesting to us in userspace. > > ZARCH_ACTIVE is set when the system is in 64-bit mode, i.e. you've booted > with a 64-bit kernel. Note that this says nothing about the address > decoding mode -- this bit can be set while the PSW is set for 31-bit > address translation, e.g. running a 32-bit program on a 64-bit kernel. > So in short we never use ZARCH in QEMU, so we probably don't want to have this #define, nor add it at the same time as FACILITY_ZARCH_ACTIVE.
On Fri, Jun 11, 2010 at 06:13:49AM -0700, Richard Henderson wrote: > On 06/11/2010 01:06 AM, Aurelien Jarno wrote: > >> That said, all the hardware to which either I or agraf have access are the latest > >> z10 machines. Frankly I expect that to be true of most if not all machines, since > >> I think it's just a microcode update which everyone with an active support contract > >> can get. > >> > > > > FYI, that's the /proc/cpuinfo of s390 machines I have (more or less) > > access: > > > > features : esan3 zarch msa ldisp > > features : esan3 zarch stfle msa ldisp eimm dfp > > features : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs > > Interesting that your first one doesn't have stfle. That one will have to > go through the SIGILL path. I would be very interested to have you test > that code path. I have tried, it correctly detects zarch and ldisp. > Also, what era is that second machine without highgprs? Is it running an > old kernel, or a 32-bit kernel? > I have very few infos about it, it's an IBM System z10 machine running a 64-bit 2.6.26 kernel.
On 06/13/2010 03:49 AM, Aurelien Jarno wrote: >> Also, what era is that second machine without highgprs? Is it running an >> old kernel, or a 32-bit kernel? > > I have very few infos about it, it's an IBM System z10 machine running a > 64-bit 2.6.26 kernel. Ah, I see it now: ea2a4d3a3a929ef494952bba57a0ef1a8a877881 [S390] 64-bit register support for 31-bit processes which adds a mechanism to pass the high parts of the gprs in the ucontext to the 31-bit signal handler, and adds a spot for them in the 31-bit core dump. It doesn't change the actual saving of registers within the kernel. Since we take asynchronous signals and return from them (as opposed to always longjmping out), we cannot use the full 64-bit register within a 31-bit process without having that bit set in HWCAP. Something to remember if we ever implement TCG for 31-bit mode. At the moment we only allow KVM in 31-bit mode. r~
On Sun, Jun 13, 2010 at 09:02:40AM -0700, Richard Henderson wrote: > On 06/13/2010 03:49 AM, Aurelien Jarno wrote: > >> Also, what era is that second machine without highgprs? Is it running an > >> old kernel, or a 32-bit kernel? > > > > I have very few infos about it, it's an IBM System z10 machine running a > > 64-bit 2.6.26 kernel. > > Ah, I see it now: ea2a4d3a3a929ef494952bba57a0ef1a8a877881 > > [S390] 64-bit register support for 31-bit processes > > which adds a mechanism to pass the high parts of the gprs > in the ucontext to the 31-bit signal handler, and adds a > spot for them in the 31-bit core dump. > > It doesn't change the actual saving of registers within > the kernel. Since we take asynchronous signals and return > from them (as opposed to always longjmping out), we cannot > use the full 64-bit register within a 31-bit process without > having that bit set in HWCAP. > > Something to remember if we ever implement TCG for 31-bit mode. > At the moment we only allow KVM in 31-bit mode. > Is KVM in 31-bit mode actually functional?
On 13.06.2010, at 18:44, Aurelien Jarno wrote: > On Sun, Jun 13, 2010 at 09:02:40AM -0700, Richard Henderson wrote: >> On 06/13/2010 03:49 AM, Aurelien Jarno wrote: >>>> Also, what era is that second machine without highgprs? Is it running an >>>> old kernel, or a 32-bit kernel? >>> >>> I have very few infos about it, it's an IBM System z10 machine running a >>> 64-bit 2.6.26 kernel. >> >> Ah, I see it now: ea2a4d3a3a929ef494952bba57a0ef1a8a877881 >> >> [S390] 64-bit register support for 31-bit processes >> >> which adds a mechanism to pass the high parts of the gprs >> in the ucontext to the 31-bit signal handler, and adds a >> spot for them in the 31-bit core dump. >> >> It doesn't change the actual saving of registers within >> the kernel. Since we take asynchronous signals and return >> from them (as opposed to always longjmping out), we cannot >> use the full 64-bit register within a 31-bit process without >> having that bit set in HWCAP. >> >> Something to remember if we ever implement TCG for 31-bit mode. >> At the moment we only allow KVM in 31-bit mode. >> > > Is KVM in 31-bit mode actually functional? I'm not aware of anything preventing it to be. But I honestly haven't tried. As long as all hypercall parameters stay within the first 32/31 bits, things should be safe. Alex
On 06/13/2010 03:23 PM, Alexander Graf wrote: > On 13.06.2010, at 18:44, Aurelien Jarno wrote: >> Is KVM in 31-bit mode actually functional? > > I'm not aware of anything preventing it to be. But I honestly haven't > tried. As long as all hypercall parameters stay within the first > 32/31 bits, things should be safe. On the other hand, is there any point in supporting it? This does seem to be a case for which it does seem like having the extra VM space (KVM+TCG) and the extra register size (TCG) is extremely helpful. I'd be just as happy to adjust the configury to actively prevent compilation in 31-bit mode, rather than pretend it might work and never bother to test it... r~
Am 14.06.2010 um 18:20 schrieb Richard Henderson <rth@twiddle.net>: > On 06/13/2010 03:23 PM, Alexander Graf wrote: >> On 13.06.2010, at 18:44, Aurelien Jarno wrote: >>> Is KVM in 31-bit mode actually functional? >> >> I'm not aware of anything preventing it to be. But I honestly haven't >> tried. As long as all hypercall parameters stay within the first >> 32/31 bits, things should be safe. > > On the other hand, is there any point in supporting it? > This does seem to be a case for which it does seem like > having the extra VM space (KVM+TCG) and the extra register > size (TCG) is extremely helpful. > > I'd be just as happy to adjust the configury to actively > prevent compilation in 31-bit mode, rather than pretend > it might work and never bother to test it... Yeah, I agree. 31-bit is really deprecated by now anyways. Aurelien was the one interested in it. Alex >
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 3944cb1..d99bb5c 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -229,6 +229,17 @@ static void *qemu_st_helpers[4] = { static uint8_t *tb_ret_addr; +/* A list of relevant facilities used by this translator. Some of these + are required for proper operation, and these are checked at startup. */ + +#define FACILITY_ZARCH (1ULL << (63 - 1)) +#define FACILITY_ZARCH_ACTIVE (1ULL << (63 - 2)) +#define FACILITY_LONG_DISP (1ULL << (63 - 18)) +#define FACILITY_EXT_IMM (1ULL << (63 - 21)) +#define FACILITY_GEN_INST_EXT (1ULL << (63 - 34)) + +static uint64_t facilities; + static void patch_reloc(uint8_t *code_ptr, int type, tcg_target_long value, tcg_target_long addend) { @@ -1177,6 +1188,106 @@ static const TCGTargetOpDef s390_op_defs[] = { { -1 }, }; +/* ??? Linux kernels provide an AUXV entry AT_HWCAP that provides most of + this information. However, getting at that entry is not easy this far + away from main. Our options are: start searching from environ, but + that fails as soon as someone does a setenv in between. Read the data + from /proc/self/auxv. Or do the probing ourselves. The only thing + extra that AT_HWCAP gives us is HWCAP_S390_HIGH_GPRS, which indicates + that the kernel saves all 64-bits of the registers around traps while + in 31-bit mode. But this is true of all "recent" kernels (ought to dig + back and see from when this might not be true). */ + +#include <signal.h> + +static volatile sig_atomic_t got_sigill; + +static void sigill_handler(int sig) +{ + got_sigill = 1; +} + +static void query_facilities(void) +{ + struct sigaction sa_old, sa_new; + register int r0 __asm__("0"); + register void *r1 __asm__("1"); + int fail; + + memset(&sa_new, 0, sizeof(sa_new)); + sa_new.sa_handler = sigill_handler; + sigaction(SIGILL, &sa_new, &sa_old); + + /* First, try STORE FACILITY LIST EXTENDED. If this is present, then + we need not do any more probing. Unfortunately, this itself is an + extension and the original STORE FACILITY LIST instruction is + kernel-only, storing its results at absolute address 200. */ + /* stfle 0(%r1) */ + r1 = &facilities; + asm volatile(".word 0xb2b0,0x1000" + : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc"); + + if (got_sigill) { + /* STORE FACILITY EXTENDED is not available. Probe for one of each + kind of instruction that we're interested in. */ + /* ??? Possibly some of these are in practice never present unless + the store-facility-extended facility is also present. But since + that isn't documented it's just better to probe for each. */ + + /* Test for z/Architecture. Required even in 31-bit mode. */ + got_sigill = 0; + /* agr %r0,%r0 */ + asm volatile(".word 0xb908,0x0000" : "=r"(r0) : : "cc"); + if (!got_sigill) { + facilities |= FACILITY_ZARCH | FACILITY_ZARCH_ACTIVE; + } + + /* Test for long displacement. */ + got_sigill = 0; + /* ly %r0,0(%r1) */ + r1 = &facilities; + asm volatile(".word 0xe300,0x1000,0x0058" + : "=r"(r0) : "r"(r1) : "cc"); + if (!got_sigill) { + facilities |= FACILITY_LONG_DISP; + } + + /* Test for extended immediates. */ + got_sigill = 0; + /* afi %r0,0 */ + asm volatile(".word 0xc209,0x0000,0x0000" : : : "cc"); + if (!got_sigill) { + facilities |= FACILITY_EXT_IMM; + } + + /* Test for general-instructions-extension. */ + got_sigill = 0; + /* msfi %r0,1 */ + asm volatile(".word 0xc201,0x0000,0x0001"); + if (!got_sigill) { + facilities |= FACILITY_GEN_INST_EXT; + } + } + + sigaction(SIGILL, &sa_old, NULL); + + /* The translator currently uses these extensions unconditionally. + Pruning this back to the base ESA/390 architecture doesn't seem + worthwhile, since even the KVM target requires z/Arch. */ + fail = 0; + if ((facilities & FACILITY_ZARCH_ACTIVE) == 0) { + fprintf(stderr, "TCG: z/Arch facility is required\n"); + fail = 1; + } + if ((facilities & FACILITY_LONG_DISP) == 0) { + fprintf(stderr, "TCG: long-displacement facility is required\n"); + fail = 1; + } + if (fail) { + exit(-1); + } +} + void tcg_target_init(TCGContext *s) { #if !defined(CONFIG_USER_ONLY) @@ -1186,6 +1297,8 @@ void tcg_target_init(TCGContext *s) } #endif + query_facilities(); + tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
Verify that we have all the instruction extensions that we generate. Future patches can tailor code generation to the set of instructions that are present. Signed-off-by: Richard Henderson <rth@twiddle.net> --- tcg/s390/tcg-target.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 113 insertions(+), 0 deletions(-)