SVM support]
PATCH 1/1 SVM support]
Forwarded, as requested.
-------- Forwarded Message --------
Quoted 403 lines
From: Alexander Graf <[email protected]>
To: J.Mayer <[email protected]>
Subject: Re: [Qemu-devel] [PATCH] SVM support
Date: Tue, 18 Sep 2007 13:51:26 +0200Quoted 197 lines · J. Mayer
Quoted 131 lines · Alexander Graf
Quoted 98 lines · Jocelyn Mayer
Quoted 86 lines · Alexander Graf
Quoted 63 lines · J. Mayer
Quoted 16 lines · Alexander Graf
Quoted 13 lines · Thiemo Seufer
Quoted 9 lines · Alexander Graf
Thanks to Michael Peter who tried the patch on an x86 host I found some
compilation problems.
This updated patch addresses these issues and thus should compile on
every platform for every target available.[...]
Quoted 6 lines
Quoted 3 lines
Wow sorry about that, looks like I missed these.
Index:
qemu-0.9.0.cvs/exec-all.h
==================================================================
=exec-all.h +0
-0@@ -166,6 +166,7 @@ static inline int tlb_set_page(CPUState typedef struct TranslationBlock { target_ulong pc; /* simulated PC corresponding to thisblock (EIP
+ CS base) */
target_ulongcs_base; /* CS base for this block */
+uint64_tintercept; /* SVM intercept vector */
unsigned int flags; /* flags defining in which context the
code was
generated */
uint16_tsize; /* size of target code for this block
(1 <=
size <=TARGET_PAGE_SIZE) */
Index:qemu-0.9.0.cvs/cpu-all.h
==================================================================
=cpu-all.h +0
-0@@ -715,6 +715,7 @@ extern int code_copy_enabled;#define CPU_INTERRUPT_HALT 0x20/* CPU halt wanted */ #define CPU_INTERRUPT_SMI 0x40/* (x86 only) SMI interrupt pending
*/
#defineCPU_INTERRUPT_DEBUG0x80/* Debug event occured. */
+#defineCPU_INTERRUPT_VIRQ0x100/* virtual interrupt
pending. */void
cpu_interrupt(CPUState *s, int mask); voidcpu_reset_interrupt(CPUState *env, int mask);Quoted 15 lines
Those two patches look ugly to me as target specific features should
never go in generic code or structures.
TheCPU_INTERRUPTflags should just contain information about the emulator behavior, thusCPU_INTERRUPT_TIMER,CPU_INTERRUPT_SMIare to be
removed. Target specific informations about the exception nature should
go in the CPUState structure... Then, adding aCPU_INTERRUPT_VIRQseems
not a good idea at all: it's outside of the generic emulator scope and
pointless for most targets.I don't see any practical reason not to do it this way. We could define
aCPU_INTERRUPT_TARGETinterrupt, that stores the information in a the
target specific CPUState, but this would hit performance (marginallyQuoted 9 lines
though) and does not improve the situation. I don't think that we should
should forcefully try to seperate targets where we are not even close to
running out of constants. If everyone on this list sees the situation as
Jocelyn does, I would be fine with writing a patch that puts target specific interrupts to the specific targets.Quoted 15 lines
I was to do the same to add some functionality to the PowerPC target,
long time ago, and Fabrice Bellard convinced me not to do and agreed it
has been a bad idea to add the target specificCPU_INTERRUPT_xxxflags.
Then I did manage the PowerPC target to use only genericCPU_INTERRUPT_xxxand put all other target specific informations in the
CPUState structure. It absolutelly changes nothing in terms of functionality nor performance. The only thing is that it makes the generic parts simpler and could even allow thecpu_execfunction to contain almost no target specific code, which would really great imho.I can give that a try :-). Sounds reasonable for me.
[Next message]
Oh well I just thought about this a bit more and while stumbling acrossCPU_INTERRUPT_FIQwhich does the same thing one major problem came to me
on that one: Priority. Real interrupts have priority over virtual interrupts so the VIRQs have to be processed after HARD IRQs, whereas SMIs and NMIs have to be taken care of before the HARD IRQs. It simply
wouldn't work out to generalize the IRQs, just as it would not work with
the VIRQ, as it has to be handled as a real IRQ but without accessing the APIC which has to be done for HARD IRQs.Quoted 1 line
I guess we're stuck with what's there now.
Priorities are not an issue, you can take a look to the
ppc_hw_interruptfunction
to see how the PowerPC emulation code manages priorities and masking between
10 different hardware interruption sources. The code could be better (I wanted
to preserve existing code) but it's a solution that actually works... But looking better the x86 emulation code, I agree that if you don't want to change it
too much, you have to add a flag. The other solution (and best, imho) would be
to do the same as what has been done for PowerPC: just let the generic code in
thecpu_execloop and move the x86 specific code somewhere in target-i386 code.
Going this way, I see no reason why the interruption code in thecpu_execloop
could not finally become:interrupt_request = env->interrupt_request; if (__builtin_expect(interrupt_request, 0)) { if (interrupt_request & CPU_INTERRUPT_DEBUG) { env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; env->exception_index = EXCP_DEBUG; cpu_loop_exit(); } if (interrupt_request & CPU_INTERRUPT_HALT) { env->interrupt_request &= ~CPU_INTERRUPT_HALT; env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); } if (interrupt_request & CPU_INTERRUPT_HARD) { hw_interrupt(env); if (env->pending_interrupts == 0) env->interrupt_request &= ~CPU_INTERRUPT_HARD; #if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; #endif } /* Don't use the cached interupt_request value, do_interrupt may have updated the EXITTB flag. */ if (interrupt_request & CPU_INTERRUPT_EXITTB) { env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */ #if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; #endif } if (interrupt_request & CPU_INTERRUPT_EXIT) { env->interrupt_request &= ~CPU_INTERRUPT_EXIT; env->exception_index = EXCP_INTERRUPT; cpu_loop_exit(); } }Quoted 6 lines
All the targets specific tricks could be done in the
hw_interruptroutine. And the generic code
would become much more readable. But this needs some works (not so much) and intensive tests...
And I guess nobody feels like taking this risk right now ;-) But I think this will have to be done someday...I definitely agree with you on that one. The current interrupt handlers are filled with #ifdefs and not easily readable. This is a different task though and maybe I will get the time to do this. I believe it should be done "all archs at once" though, so either we use the current method (adding non-gerneric interrupts) for now and tidy up everything later on or tidy up the code now and port the svm patch on that. As I don't see the cleanup coming in the near future I'd vote for including it now and have it reworked at once when someone feels dare enough to clean up the whole generic interrupt handler.
Nevertheless I really do like the idea of having a cleaned up interrupt handler. This is a different patch though and is rather a TODO than anything that should be mangled with the svm patch.
Quoted 56 lines
Quoted 34 lines
Quoted 22 lines
Quoted 11 lines
Quoted 11 lines
For the same reason, the intercept field in the TB structure seems not
acceptable, as TB specific target informations are already to be stored
in the flags field. As intercept seems only to be a bit field, it should
go, in a way or another, in tb flags. And as it seems that someQuoted 10 lines
TB flags is a 32-bit bitfield, where several bits are already used. Currently SVM supports 45 intercepts and each combination can generate a
different TB, as we do not want to reduce performance for the non-intercepted case. Think of the intercept field as flags2, that could
be used by other virtualization implementations on other architectures
too (though I do not know of any)Quoted 11 lines
So, why not make it generic and extend the flag field to as many bits as
you need ? Intercept is x86 specific and has no meaning outside of this
scope. Having more bits for flags is generic and may be useful for some
other targets... The easy way is to convert flag to 64 bits, if you have
enough bits. Another way is to make it a table, but this may need changes in all targets code...Quoted 9 lines
I think it might be quite a bad idea to extend flags until everything fits in there. I'm planning on implementing VMX as well and there are intercepts too so the meaning of the different fields change and I would
not want that happening with the normal flags vector. What would you think of an #ifdefTARGET_I386? This way intercepts are x86 only and don't interfere with any other target architecture, but are still seperated from the flags (which is semantically correct as far as it goes for me).I don't consider as a problem that one bit in the TB flags field can have different meanings.
This field is something opaque from the generic code. I actually have the same thing in
the PowerPC emulation (even if it's not fully done for now): TB flags are just an
selection of the Machine State Register bits. Some of those bits can have different
meanings depending on the PowerPC implementation (ie CPU model). But the
only thing important is to know if the current CPUState flags are equalQuoted 8 lines
to the
TB flags, not the actual meaning of the bits. As the MSR is 32 bits on 32 bits
PowerPC implementations, I have no hesitation to use those bits directly
even if their actual meaning, from the CPU "point of view" changes. Then, imho, you should not hesitate to put those intercept bits in a generic field...Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.Quoted 90 lines
Quoted 49 lines
Quoted 19 lines
Quoted 13 lines
Quoted 13 lines
interceptions are related with functions implemented in helpers (not
micro-ops), you'd better check the interception in the helper at runtime, which would add no visible overhead (as calling a helper is
slow compared to direct micro-ops execution), then you would not need to
store those infos in the TB structure. This may even make the emulationQuoted 5 lines
This was the case in an earlier version of the patch. The current implementation you see is an optimization to make it running faster, as
there is (nearly) no need for runtime detection.Quoted 14 lines
For all interceptions related to operations in helpers, it's not a actual optimisation. Things done in helpers are slow and not widely used
(compared to the translated code, I mean), then adding a single test for
interception in a helper may not hurt global performances. You may need
TB flags only for operations you want to intercept that would be inlined
in the translated code, then maybe reduce the number of bits needed without decreasing performanced. But, not knowing a lot about x86 VM specification I may be wrong...I feel really uncomfortable with supporting hundreds of different ways
of interception. It took me days to take all the intercept checks out of
the helpers into thetranslate.c, as it is way easier to maintain and read that way. I do not like the idea of converting the intercept vector
to something internal. It's quite nice to be able to use the very same
constants as kvm does. This makes debugging really easy and you don't have to define everything twice. Additionally this way you can just set
a variable without calculating anything, which does come in handy as well.Quoted 3 lines
Basically the reason I really want to have everyting in
translate.cis
simplicity though.OK, I understand that using the same code for all interceptions can make
your coding
far easier...Quoted 19 lines
Quoted 12 lines
Quoted 11 lines
Quoted 7 lines
run faster has you won't fill the TB cache with multiple translation of
the same code each time theenv->interceptchanges, thus have chance to
avoid many TB caches flushes.This is actually intended, as I believe the emulated machine should run
as fast as before when not using any interceptionsQuoted 6 lines
It depends if those flags are to be changed often or not, which depends
on the hypervisor software in use I guess. If the flags never change,
there'll be no TB flush, I agree...Quoted 12 lines
Usually (at least that's the case with kvm) you have two different sets
of intercept flags. One for the real machine and one for the virtualized
one. There is only one minor situation where that might change but that's not worth mentioning here. Nevertheless TBs point to physical memory (afaik) so since the virtual kernel is on a different page than
the real one, we could not reuse TBs anyway so having the intercept information in the TB only helps in finding out which intercepts to check for as only a minority of the possible intercepts actually get used.Quoted 11 lines
So as far as the hypervisor do not provide shared routines to be used by
the OS,
you should never have any "collisison" between translated blocks in different environments ?
I guess you need a complete TB flush when switching between the virtualized environments.
Then, OK, the interception flags should never lead to fill the TB cache
with multiple translations
of the same blocks...Exactly. The only possible "collision" would be two virtual machines that share code on the same physical page somehow.
Cheers,
Alex
Signature · 2 lines
J. Mayer <[email protected]> Never organized
Quoted 224 lines · J. Mayer
Forwarded, as requested.
-------- Forwarded Message --------
Quoted 221 lines
From: Alexander Graf <[email protected]>
To: J.Mayer <[email protected]>
Subject: Re: [Qemu-devel] [PATCH] SVM support
Date: Tue, 18 Sep 2007 13:51:26 +0200Quoted 197 lines · J. Mayer
Quoted 131 lines · Alexander Graf
Quoted 98 lines · Jocelyn Mayer
Quoted 86 lines · Alexander Graf
Quoted 63 lines · J. Mayer
Quoted 16 lines · Alexander Graf
Quoted 13 lines · Thiemo Seufer
Quoted 9 lines · Alexander Graf
Thanks to Michael Peter who tried the patch on an x86 host I found some
compilation problems.
This updated patch addresses these issues and thus should compile on
every platform for every target available.[...]
Quoted 6 lines
Quoted 3 lines
Wow sorry about that, looks like I missed these.
Index:
qemu-0.9.0.cvs/exec-all.h
==================================================================
=exec-all.h +0
-0@@ -166,6 +166,7 @@ static inline int tlb_set_page(CPUState typedef struct TranslationBlock { target_ulong pc; /* simulated PC corresponding to thisblock (EIP
+ CS base) */
target_ulongcs_base; /* CS base for this block */
+uint64_tintercept; /* SVM intercept vector */
unsigned int flags; /* flags defining in which context the
code was
generated */
uint16_tsize; /* size of target code for this block
(1 <=
size <=TARGET_PAGE_SIZE) */
Index:qemu-0.9.0.cvs/cpu-all.h
==================================================================
=cpu-all.h +0
-0@@ -715,6 +715,7 @@ extern int code_copy_enabled;#define CPU_INTERRUPT_HALT 0x20/* CPU halt wanted */ #define CPU_INTERRUPT_SMI 0x40/* (x86 only) SMI interrupt pending
*/
#defineCPU_INTERRUPT_DEBUG0x80/* Debug event occured. */
+#defineCPU_INTERRUPT_VIRQ0x100/* virtual interrupt
pending. */void
cpu_interrupt(CPUState *s, int mask); voidcpu_reset_interrupt(CPUState *env, int mask);Quoted 15 lines
Those two patches look ugly to me as target specific features should
never go in generic code or structures.
TheCPU_INTERRUPTflags should just contain information about the emulator behavior, thusCPU_INTERRUPT_TIMER,CPU_INTERRUPT_SMIare to be
removed. Target specific informations about the exception nature should
go in the CPUState structure... Then, adding aCPU_INTERRUPT_VIRQseems
not a good idea at all: it's outside of the generic emulator scope and
pointless for most targets.I don't see any practical reason not to do it this way. We could define
aCPU_INTERRUPT_TARGETinterrupt, that stores the information in a the
target specific CPUState, but this would hit performance (marginallyQuoted 9 lines
though) and does not improve the situation. I don't think that we should
should forcefully try to seperate targets where we are not even close to
running out of constants. If everyone on this list sees the situation as
Jocelyn does, I would be fine with writing a patch that puts target specific interrupts to the specific targets.Quoted 15 lines
I was to do the same to add some functionality to the PowerPC target,
long time ago, and Fabrice Bellard convinced me not to do and agreed it
has been a bad idea to add the target specificCPU_INTERRUPT_xxxflags.
Then I did manage the PowerPC target to use only genericCPU_INTERRUPT_xxxand put all other target specific informations in the
CPUState structure. It absolutelly changes nothing in terms of functionality nor performance. The only thing is that it makes the generic parts simpler and could even allow thecpu_execfunction to contain almost no target specific code, which would really great imho.I can give that a try :-). Sounds reasonable for me.
[Next message]
Oh well I just thought about this a bit more and while stumbling acrossCPU_INTERRUPT_FIQwhich does the same thing one major problem came to me
on that one: Priority. Real interrupts have priority over virtual interrupts so the VIRQs have to be processed after HARD IRQs, whereas SMIs and NMIs have to be taken care of before the HARD IRQs. It simply
wouldn't work out to generalize the IRQs, just as it would not work with
the VIRQ, as it has to be handled as a real IRQ but without accessing the APIC which has to be done for HARD IRQs.Quoted 1 line
I guess we're stuck with what's there now.
Priorities are not an issue, you can take a look to the
ppc_hw_interruptfunction
to see how the PowerPC emulation code manages priorities and masking between
10 different hardware interruption sources. The code could be better (I wanted
to preserve existing code) but it's a solution that actually works... But looking better the x86 emulation code, I agree that if you don't want to change it
too much, you have to add a flag. The other solution (and best, imho) would be
to do the same as what has been done for PowerPC: just let the generic code in
thecpu_execloop and move the x86 specific code somewhere in target-i386 code.
Going this way, I see no reason why the interruption code in thecpu_execloop
could not finally become:interrupt_request = env->interrupt_request; if (__builtin_expect(interrupt_request, 0)) { if (interrupt_request & CPU_INTERRUPT_DEBUG) { env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; env->exception_index = EXCP_DEBUG; cpu_loop_exit(); } if (interrupt_request & CPU_INTERRUPT_HALT) { env->interrupt_request &= ~CPU_INTERRUPT_HALT; env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); } if (interrupt_request & CPU_INTERRUPT_HARD) { hw_interrupt(env); if (env->pending_interrupts == 0) env->interrupt_request &= ~CPU_INTERRUPT_HARD; #if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; #endif } /* Don't use the cached interupt_request value, do_interrupt may have updated the EXITTB flag. */ if (interrupt_request & CPU_INTERRUPT_EXITTB) { env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */ #if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; #endif } if (interrupt_request & CPU_INTERRUPT_EXIT) { env->interrupt_request &= ~CPU_INTERRUPT_EXIT; env->exception_index = EXCP_INTERRUPT; cpu_loop_exit(); } }Quoted 6 lines
All the targets specific tricks could be done in the
hw_interruptroutine. And the generic code
would become much more readable. But this needs some works (not so much) and intensive tests...
And I guess nobody feels like taking this risk right now ;-) But I think this will have to be done someday...I definitely agree with you on that one. The current interrupt handlers are filled with #ifdefs and not easily readable. This is a different task though and maybe I will get the time to do this. I believe it should be done "all archs at once" though, so either we use the current method (adding non-gerneric interrupts) for now and tidy up everything later on or tidy up the code now and port the svm patch on that. As I don't see the cleanup coming in the near future I'd vote for including it now and have it reworked at once when someone feels dare enough to clean up the whole generic interrupt handler.
The danger doing the patch "all archs at once" is that it's difficult for one to know and test all archs... But it would be a great idea to fix this at once...
If your patch is ready to be applied, then apply it as it is, especially if it helps you to go on developing new features to have it commited.
Quoted 4 lines
Quoted 4 lines
Nevertheless I really do like the idea of having a cleaned up interrupt handler. This is a different patch though and is rather a TODO than anything that should be mangled with the svm patch.
yes, those are separate works, but it may help if you can have this in mind (if it does not break too much of your code too !)...
Quoted 66 lines
Quoted 66 lines
Quoted 64 lines
Quoted 34 lines
Quoted 22 lines
Quoted 11 lines
Quoted 11 lines
For the same reason, the intercept field in the TB structure seems not
acceptable, as TB specific target informations are already to be stored
in the flags field. As intercept seems only to be a bit field, it should
go, in a way or another, in tb flags. And as it seems that someQuoted 10 lines
TB flags is a 32-bit bitfield, where several bits are already used. Currently SVM supports 45 intercepts and each combination can generate a
different TB, as we do not want to reduce performance for the non-intercepted case. Think of the intercept field as flags2, that could
be used by other virtualization implementations on other architectures
too (though I do not know of any)Quoted 11 lines
So, why not make it generic and extend the flag field to as many bits as
you need ? Intercept is x86 specific and has no meaning outside of this
scope. Having more bits for flags is generic and may be useful for some
other targets... The easy way is to convert flag to 64 bits, if you have
enough bits. Another way is to make it a table, but this may need changes in all targets code...Quoted 9 lines
I think it might be quite a bad idea to extend flags until everything fits in there. I'm planning on implementing VMX as well and there are intercepts too so the meaning of the different fields change and I would
not want that happening with the normal flags vector. What would you think of an #ifdefTARGET_I386? This way intercepts are x86 only and don't interfere with any other target architecture, but are still seperated from the flags (which is semantically correct as far as it goes for me).I don't consider as a problem that one bit in the TB flags field can have different meanings.
This field is something opaque from the generic code. I actually have the same thing in
the PowerPC emulation (even if it's not fully done for now): TB flags are just an
selection of the Machine State Register bits. Some of those bits can have different
meanings depending on the PowerPC implementation (ie CPU model). But the
only thing important is to know if the current CPUState flags are equal
to the
TB flags, not the actual meaning of the bits. As the MSR is 32 bits on 32 bits
PowerPC implementations, I have no hesitation to use those bits directly
even if their actual meaning, from the CPU "point of view" changes. Then, imho, you should not hesitate to put those intercept bits in a generic field...
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.
OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
[...]
Signature · 2 lines
J. Mayer <[email protected]> Never organized
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Maybe worth letting the target say whether it needs 32 or 64-bit flags. The flag lookup is likely to be on a hot path.
Paul
Quoted 10 lines · Paul Brook
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Maybe worth letting the target say whether it needs 32 or 64-bit flags. The flag lookup is likely to be on a hot path.
Paul
I actually don't see too much of a performance penality in that but nevertheless could you please test if the appended patch hits performance for you? This changes the tb->flags field to be 64 bits.
If it does not, please apply this to the CVS as my SVM patch now relies on it.
Cheers,
Alex
target-i386/translate.c +3 -2
@@ -95,7 +95,7 @@ typedef struct DisasContext {int singlestep_enabled;/* "hardware" single step enabled */ int jmp_opt;/* use direct block chaining for direct jumps */ int mem_index;/* select memory access functions */ -int flags;/* all execution flags */ +uint64_t flags;/* all execution flags */ struct TranslationBlock *tb;int popl_esp_hack;/* for correct popl with esp base handling */ int rip_offset;/* only used in x86_64, but left for simplicity */
@@ -6462,7 +6462,8 @@ static inline int gen_intermediate_code_DisasContext dc1, *dc = &dc1;target_ulong pc_ptr;uint16_t *gen_opc_end; -int flags, j, lj, cflags; +int j, lj, cflags; +uint64_t flags;target_ulong pc_start;target_ulong cs_base;
cpu-exec.c +2 -2
@@ -77,7 +77,7 @@ void cpu_resume_from_signal(CPUState *enstatic TranslationBlock *tb_find_slow (target_ulong pc,target_ulong cs_base, -unsigned int flags) +uint64_t flags) {TranslationBlock *tb, **ptb1;int code_gen_size;
@@ -155,7 +155,7 @@ static inline TranslationBlock *tb_find_ {TranslationBlock *tb;target_ulong cs_base, pc; -unsigned int flags; +uint64_t flags;/* we record a subset of the CPU state. It will always be the same before a given translated block
exec-all.h +1 -1
@@ -166,7 +166,7 @@ static inline int tlb_set_page(CPUState typedef struct TranslationBlock { target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ target_ulong cs_base; /* CS base for this block */ - unsigned int flags; /* flags defining in which context the code was generated */ + uint64_t flags; /* flags defining in which context the code was generated */ uint16_t size; /* size of target code for this block (1 <= size <= TARGET_PAGE_SIZE) */ uint16_t cflags; /* compile flags */
target-mips/translate.c +1 -1
@@ -6403,7 +6403,7 @@ gen_intermediate_code_internal (CPUState ctx.tb = tb; ctx.bstate =BS_NONE ;/* Restore delay slot state from the tb context. */ - ctx.hflags = tb->flags; + ctx.hflags = (uint32_t )tb->flags;/* FIXME: maybe use 64 bits here? */ restore_cpu_state (env, &ctx);#if defined(CONFIG_USER_ONLY ) ctx.mem_idx =0 ;
Quoted 10 lines · Paul Brook
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Maybe worth letting the target say whether it needs 32 or 64-bit flags. The flag lookup is likely to be on a hot path.
Paul
here comes the patch.
Quoted 8 lines · Alexander Graf
Quoted 6 lines · Paul Brook
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Quoted 7 lines
Quoted 5 lines
Maybe worth letting the target say whether it needs 32 or 64-bit flags.
The flag lookup is likely to be on a hot path.Paul
here comes the patch.
The patch looks correct to me, I'm just wondering why a cast to 32 bits is needed in mips code ?
I may be wrong, but it seems to me that TB flags are only used to be compared in tb_find_fast and tb_find_slow, which are not a very fast path (we come here when we cannot jump directly to the next tb and are not in the most time critical code) then we can afford adding a few asm instructions (I would say max 2 ?) to replace a 32 bits comparison with a 64 bits one. My feeling is that the performance loss here won't be sensible, but that may need to be proved.
Quoted 13 lines · Jocelyn Mayer
Quoted 12 lines · Alexander Graf
Quoted 10 lines · Paul Brook
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Maybe worth letting the target say whether it needs 32 or 64-bit flags.
The flag lookup is likely to be on a hot path.
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Paul
here comes the patch.
The patch looks correct to me, I'm just wondering why a cast to 32 bits is needed in mips code ?
It's not needed - I just did it so one can see that there is potential that is not used right now and someone should think about it. I'm not too much into mips so I have no clues if they have any use for more that 32 bits of flags.
Quoted 10 lines
I may be wrong, but it seems to me that TB flags are only used to be compared in
tb_find_fastandtb_find_slow, which are not a very fast path (we come here when we cannot jump directly to the next tb and are not in the most time critical code) then we can afford adding a few asm instructions (I would say max 2 ?) to replace a 32 bits comparison with a 64 bits one. My feeling is that the performance loss here won't be sensible, but that may need to be proved.
I actually don't even believe the difference can be measured at all, which is why I seperated the patches.
Cheers,
Alex
Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Maybe worth letting the target say whether it needs 32 or 64-bit flags.
The flag lookup is likely to be on a hot path.
Quoted 7 lines
I may be wrong, but it seems to me that TB flags are only used to be compared in
tb_find_fastandtb_find_slow, which are not a very fast path (we come here when we cannot jump directly to the next tb and are not in the most time critical code) then we can afford adding a few asm instructions (I would say max 2 ?) to replace a 32 bits comparison with a 64 bits one. My feeling is that the performance loss here won't be sensible, but that may need to be proved.
For some reason I thought the flags were also used in the hash lookup. This is not the case, so I withdraw my objection.
Paul
Quoted 16 lines · Paul Brook
Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Maybe worth letting the target say whether it needs 32 or 64-bit flags.
The flag lookup is likely to be on a hot path.Quoted 7 lines
I may be wrong, but it seems to me that TB flags are only used to be compared in
tb_find_fastandtb_find_slow, which are not a very fast path (we come here when we cannot jump directly to the next tb and are not in the most time critical code) then we can afford adding a few asm instructions (I would say max 2 ?) to replace a 32 bits comparison with a 64 bits one. My feeling is that the performance loss here won't be sensible, but that may need to be proved.
Quoted 2 lines
For some reason I thought the flags were also used in the hash lookup. This is not the case, so I withdraw my objection.
OK, then I feel like the flags size modification patch is acceptable. If there is no objection (and if no one commits it before ;-)), I'm ready to integrate it in the days to come.
Signature · 2 lines
J. Mayer <[email protected]> Never organized
target-i386/helper2.c +12 -3
@@ -27,6 +27,7 @@#include "cpu.h" #include "exec-all.h" +#include "svm.h" //#define DEBUG_MMU
@@ -111,10 +112,11 @@ CPUX86State *cpu_x86_init(void)CPUID_CX8 |CPUID_PGE |CPUID_CMOV | CPUID_PAT); env->pat =0x0007040600070406ULL ; + env->cpuid_ext3_features =CPUID_EXT3_SVM ; env->cpuid_ext_features =CPUID_EXT_SSE3 ; env->cpuid_features |=CPUID_FXSR |CPUID_MMX |CPUID_SSE |CPUID_SSE2 |CPUID_PAE |CPUID_SEP ; env->cpuid_features |=CPUID_APIC ; - env->cpuid_xlevel =0x80000006 ; + env->cpuid_xlevel =0x8000000e ; {const char *model_id ="QEMU Virtual CPU version " QEMU_VERSION ;int c, len, i;
@@ -131,7 +133,6 @@ CPUX86State *cpu_x86_init(void)/* currently not enabled for std i386 because not fully tested */ env->cpuid_ext2_features = (env->cpuid_features &0x0183F3FF ); env->cpuid_ext2_features |=CPUID_EXT2_LM |CPUID_EXT2_SYSCALL |CPUID_EXT2_NX ; - env->cpuid_xlevel =0x80000008 ;/* these features are needed for Win64 and aren't fully implemented */ env->cpuid_features |=CPUID_MTRR |CPUID_CLFLUSH |CPUID_MCA ;
@@ -162,6 +163,7 @@ void cpu_reset(CPUX86State *env)#ifdef CONFIG_SOFTMMU env->hflags |=HF_SOFTMMU_MASK ;#endif + env->hflags |=HF_GIF_MASK ;cpu_x86_update_cr0 (env,0x60000010 ); env->a20_mask =0xffffffff ;
@@ -865,7 +867,6 @@ int cpu_x86_handle_mmu_fault(CPUX86State do_fault_protect: error_code =PG_ERROR_P_MASK ; do_fault: - env->cr[2 ] = addr; error_code |= (is_write <<PG_ERROR_W_BIT );if (is_user) error_code |=PG_ERROR_U_MASK ;
@@ -873,8 +874,16 @@ int cpu_x86_handle_mmu_fault(CPUX86State (env->efer & MSR_EFER_NXE) && (env->cr[4] & CR4_PAE_MASK)) error_code |=PG_ERROR_I_D_MASK ; +if (INTERCEPTEDl (_exceptions,1 <<EXCP0E_PAGE )) { + stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr); + }else { + env->cr[2 ] = addr; + } env->error_code = error_code; env->exception_index =EXCP0E_PAGE ; +/* the VMM will handle this */ +if (INTERCEPTEDl (_exceptions,1 <<EXCP0E_PAGE )) +return 2 ;return 1 ; }
target-i386/translate.c +238 -5
480 lines not on this page · raw message
target-i386/cpu.h +22 -0
@@ -84,6 +84,7 @@#define DESC_AVL_MASK (1 << 20)#define DESC_P_MASK (1 << 15)#define DESC_DPL_SHIFT 13 +#define DESC_DPL_MASK (1 << DESC_DPL_SHIFT)#define DESC_S_MASK (1 << 12)#define DESC_TYPE_SHIFT 8#define DESC_A_MASK (1 << 8)
@@ -149,6 +150,8 @@#define HF_VM_SHIFT 17/* must be same as eflags */ #define HF_HALTED_SHIFT 18/* CPU halted */ #define HF_SMM_SHIFT 19/* CPU in SMM mode */ +#define HF_GIF_SHIFT 20/* if set CPU takes interrupts */ +#define HF_HIF_SHIFT 21/* shadow copy of IF_MASK when in SVM */ #define HF_CPL_MASK (3 << HF_CPL_SHIFT)#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
@@ -166,6 +169,8 @@#define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)#define HF_HALTED_MASK (1 << HF_HALTED_SHIFT)#define HF_SMM_MASK (1 << HF_SMM_SHIFT) +#define HF_GIF_MASK (1 << HF_GIF_SHIFT) +#define HF_HIF_MASK (1 << HF_HIF_SHIFT)#define CR0_PE_MASK (1 << 0)#define CR0_MP_MASK (1 << 1)
@@ -249,6 +254,8 @@#define MSR_GSBASE 0xc0000101#define MSR_KERNELGSBASE 0xc0000102 +#define MSR_VM_HSAVE_PA 0xc0010117 +/* cpuid_features bits */ #define CPUID_FP87 (1 << 0)#define CPUID_VME (1 << 1)
@@ -283,6 +290,8 @@#define CPUID_EXT2_FFXSR (1 << 25)#define CPUID_EXT2_LM (1 << 29) +#define CPUID_EXT3_SVM (1 << 2) +#define EXCP00_DIVZ 0#define EXCP01_SSTP 1#define EXCP02_NMI 2
@@ -491,6 +500,16 @@ typedef struct CPUX86State {uint32_t sysenter_eip;uint64_t efer;uint64_t star; + +target_phys_addr_t vm_hsave; +target_phys_addr_t vm_vmcb; +uint64_t intercept; +uint16_t intercept_cr_read; +uint16_t intercept_cr_write; +uint16_t intercept_dr_read; +uint16_t intercept_dr_write; +uint32_t intercept_exceptions; +#ifdef TARGET_X86_64 target_ulong lstar;target_ulong cstar;
@@ -532,6 +551,7 @@ typedef struct CPUX86State {uint32_t cpuid_xlevel;uint32_t cpuid_model[12 ];uint32_t cpuid_ext2_features; +uint32_t cpuid_ext3_features;uint32_t cpuid_apic_id;#ifdef USE_KQEMU
@@ -672,4 +692,6 @@ static inline int cpu_get_time_fast(void#include "cpu-all.h" +#include "svm.h" +#endif /* CPU_I386_H */
target-i386/op.c +85 -3
114 lines not on this page · raw message
target-i386/helper.c +521 -2
572 lines not on this page · raw message
target-i386/svm.h new file +358 -0
358 lines not on this page · raw message
cpu-exec.c +27 -2
@@ -163,6 +163,7 @@ static inline TranslationBlock *tb_find_#if defined(TARGET_I386 ) flags = env->hflags; flags |= (env->eflags & (IOPL_MASK |TF_MASK |VM_MASK )); + flags |= env->intercept; cs_base = env->segs[R_CS ].base; pc = cs_base + env->eip;#elif defined(TARGET_ARM )
@@ -373,7 +374,11 @@ int cpu_exec(CPUState *env1) tmp_T0 =T0 ;#endif interrupt_request = env->interrupt_request; -if (__builtin_expect (interrupt_request,0 )) { + if (__builtin_expect(interrupt_request, 0) +#if defined(TARGET_I386 ) + && env->hflags & HF_GIF_MASK +#endif + ) {if (interrupt_request &CPU_INTERRUPT_DEBUG ) { env->interrupt_request &= ~CPU_INTERRUPT_DEBUG ; env->exception_index =EXCP_DEBUG ;
@@ -391,6 +396,7 @@ int cpu_exec(CPUState *env1)#if defined(TARGET_I386 )if ((interrupt_request &CPU_INTERRUPT_SMI ) && !(env->hflags &HF_SMM_MASK )) { +svm_check_intercept (SVM_EXIT_SMI ); env->interrupt_request &= ~CPU_INTERRUPT_SMI ;do_smm_enter ();#if defined(__sparc__) && !defined(HOST_SOLARIS )
@@ -399,9 +405,10 @@ int cpu_exec(CPUState *env1)T0 =0 ;#endif }else if ((interrupt_request &CPU_INTERRUPT_HARD ) && - (env->eflags &IF_MASK ) && + (env->eflags &IF_MASK || env->hflags &HF_HIF_MASK ) && !(env->hflags &HF_INHIBIT_IRQ_MASK )) {int intno; +svm_check_intercept (SVM_EXIT_INTR ); env->interrupt_request &= ~CPU_INTERRUPT_HARD ; intno =cpu_get_pic_interrupt (env);if (loglevel &CPU_LOG_TB_IN_ASM ) {
@@ -415,6 +422,24 @@ int cpu_exec(CPUState *env1)#else T0 =0 ;#endif +#if !defined(CONFIG_USER_ONLY ) + } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && + (env->eflags &IF_MASK ) && !(env->hflags &HF_INHIBIT_IRQ_MASK )) { +int intno; +/* FIXME: this should respect TPR */ + env->interrupt_request &= ~CPU_INTERRUPT_VIRQ ; + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), + ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK); + intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); +if (loglevel &CPU_LOG_TB_IN_ASM ) +fprintf (logfile,"Servicing virtual hardware INT=0x%02x\n" , intno); +do_interrupt (intno,0 ,0 ,-1 ,1 ); +#if defined(__sparc__) && !defined(HOST_SOLARIS ) + tmp_T0 =0 ; +#else +T0 =0 ; +#endif +#endif }#elif defined(TARGET_PPC)#if 0
target-i386/exec.h +10 -0
@@ -506,6 +506,15 @@ void update_fp_status(void);void helper_hlt (void );void helper_monitor (void );void helper_mwait (void ); +void helper_vmrun (target_ulong addr); +void helper_vmmcall (void ); +void helper_vmload (target_ulong addr); +void helper_vmsave (target_ulong addr); +void helper_stgi (void ); +void helper_clgi (void ); +void helper_skinit (void ); +void helper_invlpga (void ); +void vmexit (uint64_t exit_code,uint64_t exit_info_1);extern const uint8_t parity_table[256 ];extern const uint8_t rclw_table[32 ];
@@ -593,3 +602,4 @@ static inline int cpu_halted(CPUState *e }return EXCP_HALTED ; } +
exec.c +5 -0
@@ -1292,6 +1292,11 @@ void cpu_abort(CPUState *env, const charvfprintf (stderr, fmt, ap);fprintf (stderr,"\n" );#ifdef TARGET_I386 +if (env->intercept &INTERCEPT_SVM_MASK ) { +/* most probably the virtual machine should not +be shut down but rather caught by the VMM */ +vmexit (SVM_EXIT_SHUTDOWN ,0 ); + }cpu_dump_state (env, stderr, fprintf,X86_DUMP_FPU |X86_DUMP_CCOP );#else cpu_dump_state (env, stderr, fprintf,0 );
cpu-all.h +1 -0
@@ -716,6 +716,7 @@ extern int code_copy_enabled;#define CPU_INTERRUPT_HALT 0x20/* CPU halt wanted */ #define CPU_INTERRUPT_SMI 0x40/* (x86 only) SMI interrupt pending */ #define CPU_INTERRUPT_DEBUG 0x80/* Debug event occured. */ +#define CPU_INTERRUPT_VIRQ 0x100/* virtual interrupt pending. */ void cpu_interrupt (CPUState *s,int mask);void cpu_reset_interrupt (CPUState *env,int mask);
Quoted 229 lines · J. Mayer
Quoted 227 lines · J. Mayer
Forwarded, as requested.
-------- Forwarded Message --------
Quoted 224 lines
From: Alexander Graf <[email protected]>
To: J.Mayer <[email protected]>
Subject: Re: [Qemu-devel] [PATCH] SVM support
Date: Tue, 18 Sep 2007 13:51:26 +0200Quoted 200 lines · J. Mayer
Quoted 131 lines · Alexander Graf
Quoted 98 lines · Jocelyn Mayer
Quoted 86 lines · Alexander Graf
Quoted 63 lines · J. Mayer
Quoted 16 lines · Alexander Graf
Quoted 13 lines · Thiemo Seufer
Quoted 9 lines · Alexander Graf
Thanks to Michael Peter who tried the patch on an x86 host I found some
compilation problems.
This updated patch addresses these issues and thus should compile on
every platform for every target available.[...]
Quoted 6 lines
Quoted 3 lines
Wow sorry about that, looks like I missed these.
Index:
qemu-0.9.0.cvs/exec-all.h
==================================================================
=exec-all.h +0
-0@@ -166,6 +166,7 @@ static inline int tlb_set_page(CPUState typedef struct TranslationBlock { target_ulong pc; /* simulated PC corresponding to thisblock (EIP
+ CS base) */
target_ulongcs_base; /* CS base for this block */
+uint64_tintercept; /* SVM intercept vector */
unsigned int flags; /* flags defining in which context the
code was
generated */
uint16_tsize; /* size of target code for this block
(1 <=
size <=TARGET_PAGE_SIZE) */
Index:qemu-0.9.0.cvs/cpu-all.h
==================================================================
=cpu-all.h +0
-0@@ -715,6 +715,7 @@ extern int code_copy_enabled;#define CPU_INTERRUPT_HALT 0x20/* CPU halt wanted */ #define CPU_INTERRUPT_SMI 0x40/* (x86 only) SMI interrupt pending
*/
#defineCPU_INTERRUPT_DEBUG0x80/* Debug event occured. */
+#defineCPU_INTERRUPT_VIRQ0x100/* virtual interrupt
pending. */void
cpu_interrupt(CPUState *s, int mask); voidcpu_reset_interrupt(CPUState *env, int mask);Quoted 15 lines
Those two patches look ugly to me as target specific features should
never go in generic code or structures.
TheCPU_INTERRUPTflags should just contain information about the emulator behavior, thusCPU_INTERRUPT_TIMER,CPU_INTERRUPT_SMIare to be
removed. Target specific informations about the exception nature should
go in the CPUState structure... Then, adding aCPU_INTERRUPT_VIRQseems
not a good idea at all: it's outside of the generic emulator scope and
pointless for most targets.I don't see any practical reason not to do it this way. We could define
aCPU_INTERRUPT_TARGETinterrupt, that stores the information in a the
target specific CPUState, but this would hit performance (marginallyQuoted 9 lines
though) and does not improve the situation. I don't think that we should
should forcefully try to seperate targets where we are not even close to
running out of constants. If everyone on this list sees the situation as
Jocelyn does, I would be fine with writing a patch that puts target specific interrupts to the specific targets.Quoted 15 lines
I was to do the same to add some functionality to the PowerPC target,
long time ago, and Fabrice Bellard convinced me not to do and agreed it
has been a bad idea to add the target specificCPU_INTERRUPT_xxxflags.
Then I did manage the PowerPC target to use only genericCPU_INTERRUPT_xxxand put all other target specific informations in the
CPUState structure. It absolutelly changes nothing in terms of functionality nor performance. The only thing is that it makes the generic parts simpler and could even allow thecpu_execfunction to contain almost no target specific code, which would really great imho.I can give that a try :-). Sounds reasonable for me.
[Next message]
Oh well I just thought about this a bit more and while stumbling acrossCPU_INTERRUPT_FIQwhich does the same thing one major problem came to me
on that one: Priority. Real interrupts have priority over virtual interrupts so the VIRQs have to be processed after HARD IRQs, whereas SMIs and NMIs have to be taken care of before the HARD IRQs. It simply
wouldn't work out to generalize the IRQs, just as it would not work with
the VIRQ, as it has to be handled as a real IRQ but without accessing the APIC which has to be done for HARD IRQs.Quoted 1 line
I guess we're stuck with what's there now.
Priorities are not an issue, you can take a look to the
ppc_hw_interruptfunction
to see how the PowerPC emulation code manages priorities and masking between
10 different hardware interruption sources. The code could be better (I wanted
to preserve existing code) but it's a solution that actually works... But looking better the x86 emulation code, I agree that if you don't want to change it
too much, you have to add a flag. The other solution (and best, imho) would be
to do the same as what has been done for PowerPC: just let the generic code in
thecpu_execloop and move the x86 specific code somewhere in target-i386 code.
Going this way, I see no reason why the interruption code in thecpu_execloop
could not finally become:interrupt_request = env->interrupt_request; if (__builtin_expect(interrupt_request, 0)) { if (interrupt_request & CPU_INTERRUPT_DEBUG) { env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; env->exception_index = EXCP_DEBUG; cpu_loop_exit(); } if (interrupt_request & CPU_INTERRUPT_HALT) { env->interrupt_request &= ~CPU_INTERRUPT_HALT; env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); } if (interrupt_request & CPU_INTERRUPT_HARD) { hw_interrupt(env); if (env->pending_interrupts == 0) env->interrupt_request &= ~CPU_INTERRUPT_HARD; #if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; #endif } /* Don't use the cached interupt_request value, do_interrupt may have updated the EXITTB flag. */ if (interrupt_request & CPU_INTERRUPT_EXITTB) { env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */ #if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; #endif } if (interrupt_request & CPU_INTERRUPT_EXIT) { env->interrupt_request &= ~CPU_INTERRUPT_EXIT; env->exception_index = EXCP_INTERRUPT; cpu_loop_exit(); } }Quoted 6 lines
All the targets specific tricks could be done in the
hw_interruptroutine. And the generic code
would become much more readable. But this needs some works (not so much) and intensive tests...
And I guess nobody feels like taking this risk right now ;-) But I think this will have to be done someday...I definitely agree with you on that one. The current interrupt handlers are filled with #ifdefs and not easily readable. This is a different task though and maybe I will get the time to do this. I believe it should be done "all archs at once" though, so either we use the current method (adding non-gerneric interrupts) for now and tidy up everything later on or tidy up the code now and port the svm patch on that. As I don't see the cleanup coming in the near future I'd vote for including it now and have it reworked at once when someone feels dare enough to clean up the whole generic interrupt handler.
Quoted 5 lines
The danger doing the patch "all archs at once" is that it's difficult for one to know and test all archs... But it would be a great idea to fix this at once...
If your patch is ready to be applied, then apply it as it is, especially if it helps you to go on developing new features to have it commited.
As I do not have any commit rights, I need someone to apply this for me ;-).
I'm not too sure about new features getting in soon though, as I will very soon have to write my bachelor thesis and am not allowed to write it on anything technical like qemu.
Quoted 75 lines
Quoted 5 lines
Quoted 5 lines
Nevertheless I really do like the idea of having a cleaned up interrupt handler. This is a different patch though and is rather a TODO than anything that should be mangled with the svm patch.
yes, those are separate works, but it may help if you can have this in mind (if it does not break too much of your code too !)...
Quoted 66 lines
Quoted 66 lines
Quoted 64 lines
Quoted 34 lines
Quoted 22 lines
Quoted 11 lines
Quoted 11 lines
For the same reason, the intercept field in the TB structure seems not
acceptable, as TB specific target informations are already to be stored
in the flags field. As intercept seems only to be a bit field, it should
go, in a way or another, in tb flags. And as it seems that someQuoted 10 lines
TB flags is a 32-bit bitfield, where several bits are already used. Currently SVM supports 45 intercepts and each combination can generate a
different TB, as we do not want to reduce performance for the non-intercepted case. Think of the intercept field as flags2, that could
be used by other virtualization implementations on other architectures
too (though I do not know of any)Quoted 11 lines
So, why not make it generic and extend the flag field to as many bits as
you need ? Intercept is x86 specific and has no meaning outside of this
scope. Having more bits for flags is generic and may be useful for some
other targets... The easy way is to convert flag to 64 bits, if you have
enough bits. Another way is to make it a table, but this may need changes in all targets code...Quoted 9 lines
I think it might be quite a bad idea to extend flags until everything fits in there. I'm planning on implementing VMX as well and there are intercepts too so the meaning of the different fields change and I would
not want that happening with the normal flags vector. What would you think of an #ifdefTARGET_I386? This way intercepts are x86 only and don't interfere with any other target architecture, but are still seperated from the flags (which is semantically correct as far as it goes for me).I don't consider as a problem that one bit in the TB flags field can have different meanings.
This field is something opaque from the generic code. I actually have the same thing in
the PowerPC emulation (even if it's not fully done for now): TB flags are just an
selection of the Machine State Register bits. Some of those bits can have different
meanings depending on the PowerPC implementation (ie CPU model). But the
only thing important is to know if the current CPUState flags are equal
to the
TB flags, not the actual meaning of the bits. As the MSR is 32 bits on 32 bits
PowerPC implementations, I have no hesitation to use those bits directly
even if their actual meaning, from the CPU "point of view" changes. Then, imho, you should not hesitate to put those intercept bits in a generic field...
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Ok, I will try to shift the intercepts in an
uint_64flags variable in the TB.OK, great. Having 64 bits may also help for additional (ie future...) features in PowerPC 64 emulation.
Changed the patch and it seems to work for me.
Cheers,
Alex