Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/23/2016 2:11 PM, Julien Grall wrote: Hello, On 23/06/16 06:49, Corneliu ZUZU wrote: On 6/23/2016 8:31 AM, Corneliu ZUZU wrote: On 6/22/2016 10:41 PM, Julien Grall wrote: On 22/06/2016 20:37, Corneliu ZUZU wrote: I've also realized that it's a bit complicated to avoid writing HCR from 2 places. That's because: - p2m_restore_state is part of the process of switching to another vCPU and the HCR write _must be committed_ here because other components depend on that, like address-translation functions - I want vm_event_vcpu_enter to be called _after_ the switch to the vCPU is completed - I want HCR_TVM to be set in vm_event_vcpu_enter because setting necessary traps _for cr vm-events_ to work should be done there (setting HCR_TVM bit makes sense to be there and the purpose is to centralize operations such as this for code comprehensibility; also, on the X86 counterpart a similar operation is done for trapping CR3, so it would be nice to keep the symmetry) Would it be such a stretch to have HCR written in 2 places? (the second time happens rarely anyway: it's unlikely(..) to have to do the write in vm_event_vcpu_enter) Not really. It was mostly to avoid setting/clearing HCR bits in different place in the code. It makes more difficult to know what is the final result of the register. Anyway, let's skip it for now, if it is too difficult. Regards, Then perhaps something like the following would be suitable: 1. store hcr in arch_domain (register_t hcr) 2. add a function in asm-arm/processor.h (or where else?) which only does: static inline void update_hcr(struct domain *d) { WRITE_SYSREG(d->arch.hcr, HCR_EL2); isb(); } 3. modify p2m_restore_state to do: n->domain->arch.hcr &= ~HCR_VM; update_hcr(n->domain); p2m_load_VTTBR(n->domain); n->domain->arch.hcr |= HCR_VM; if ( is_32bit_domain(n->domain) ) n->domain->arch.hcr &= ~HCR_RW; else n->domain->arch.hcr |= HCR_RW; This is not safe at all, p2m_restore_state is vCPU specific at you modify domain information. However, if we store the hcr per domain, overriding every context switch is pointless as the domain will always be 32-bit/64-bit. Oh right, the RW bit needs not be set/unset anymore with this change. update_hcr(n->domain); WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); 4. and vcpu_enter_adjust_traps to if ( unlikely(0 != v->domain->arch.monitor.write_ctrlreg_enabled) ) { if ( likely(v->domain->arch.hcr & HCR_TVM) ) return; v->domain->arch.hcr |= HCR_TVM; } else { if ( likely(!(v->domain->arch.hcr & HCR_TVM)) ) return; v->domain->arch.hcr &= ~HCR_TVM; } This does not need to be done in vcpu_enter_adjust_traps everytime. You can set the bit in arch.hcr in DOMCTL_MONITOR_EVENT_WRITE_CTRLREG. I wanted to keep X86-ARM symmetry and it seemed more intuitive to have these kind of adjustments with the vcpu_enter code motion. But now that I think about it, given the fact that we have the guarantee that after monitor_domctl and before reentering the vCPU p2m_restore_state gets called (due to domain_pause/domain_unpause) - thus actually committing the hcr update at the proper time - technically monitor_domctl _is_ the optimal place to set arch.hcr in. In conclusion, I'm thinking of discarding the entire idea of introducing vm_event_vcpu_enter, it seems to me now that this would also render a simpler code. update_hcr(v->domain); That way at least it's easier to follow where update_hcr is called. I don't see much reason to store the value in the domain and have multiple update_hcr. If we store the value, then we should only call update_hcr once when returning to the guest. Yep, that will happen with the above-mentioned discarding of vm_event_vcpu_enter idea. And also set the initial value of HCR at the moment of creation, i.e. in arch_domain_create as d->arch.hcr = READ_SYSREG(HCR_EL2) We control the value of HCR_EL2, so it would be better to assign the list of flags here. Right, that will happen too. Regards, Thanks for the useful insights, Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
Hello, On 23/06/16 06:49, Corneliu ZUZU wrote: On 6/23/2016 8:31 AM, Corneliu ZUZU wrote: On 6/22/2016 10:41 PM, Julien Grall wrote: On 22/06/2016 20:37, Corneliu ZUZU wrote: I've also realized that it's a bit complicated to avoid writing HCR from 2 places. That's because: - p2m_restore_state is part of the process of switching to another vCPU and the HCR write _must be committed_ here because other components depend on that, like address-translation functions - I want vm_event_vcpu_enter to be called _after_ the switch to the vCPU is completed - I want HCR_TVM to be set in vm_event_vcpu_enter because setting necessary traps _for cr vm-events_ to work should be done there (setting HCR_TVM bit makes sense to be there and the purpose is to centralize operations such as this for code comprehensibility; also, on the X86 counterpart a similar operation is done for trapping CR3, so it would be nice to keep the symmetry) Would it be such a stretch to have HCR written in 2 places? (the second time happens rarely anyway: it's unlikely(..) to have to do the write in vm_event_vcpu_enter) Not really. It was mostly to avoid setting/clearing HCR bits in different place in the code. It makes more difficult to know what is the final result of the register. Anyway, let's skip it for now, if it is too difficult. Regards, Then perhaps something like the following would be suitable: 1. store hcr in arch_domain (register_t hcr) 2. add a function in asm-arm/processor.h (or where else?) which only does: static inline void update_hcr(struct domain *d) { WRITE_SYSREG(d->arch.hcr, HCR_EL2); isb(); } 3. modify p2m_restore_state to do: n->domain->arch.hcr &= ~HCR_VM; update_hcr(n->domain); p2m_load_VTTBR(n->domain); n->domain->arch.hcr |= HCR_VM; if ( is_32bit_domain(n->domain) ) n->domain->arch.hcr &= ~HCR_RW; else n->domain->arch.hcr |= HCR_RW; This is not safe at all, p2m_restore_state is vCPU specific at you modify domain information. However, if we store the hcr per domain, overriding every context switch is pointless as the domain will always be 32-bit/64-bit. update_hcr(n->domain); WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); 4. and vcpu_enter_adjust_traps to if ( unlikely(0 != v->domain->arch.monitor.write_ctrlreg_enabled) ) { if ( likely(v->domain->arch.hcr & HCR_TVM) ) return; v->domain->arch.hcr |= HCR_TVM; } else { if ( likely(!(v->domain->arch.hcr & HCR_TVM)) ) return; v->domain->arch.hcr &= ~HCR_TVM; } This does not need to be done in vcpu_enter_adjust_traps everytime. You can set the bit in arch.hcr in DOMCTL_MONITOR_EVENT_WRITE_CTRLREG. update_hcr(v->domain); That way at least it's easier to follow where update_hcr is called. I don't see much reason to store the value in the domain and have multiple update_hcr. If we store the value, then we should only call update_hcr once when returning to the guest. And also set the initial value of HCR at the moment of creation, i.e. in arch_domain_create as d->arch.hcr = READ_SYSREG(HCR_EL2) We control the value of HCR_EL2, so it would be better to assign the list of flags here. Regards, -- Julien Grall ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/23/2016 8:31 AM, Corneliu ZUZU wrote: On 6/22/2016 10:41 PM, Julien Grall wrote: On 22/06/2016 20:37, Corneliu ZUZU wrote: I've also realized that it's a bit complicated to avoid writing HCR from 2 places. That's because: - p2m_restore_state is part of the process of switching to another vCPU and the HCR write _must be committed_ here because other components depend on that, like address-translation functions - I want vm_event_vcpu_enter to be called _after_ the switch to the vCPU is completed - I want HCR_TVM to be set in vm_event_vcpu_enter because setting necessary traps _for cr vm-events_ to work should be done there (setting HCR_TVM bit makes sense to be there and the purpose is to centralize operations such as this for code comprehensibility; also, on the X86 counterpart a similar operation is done for trapping CR3, so it would be nice to keep the symmetry) Would it be such a stretch to have HCR written in 2 places? (the second time happens rarely anyway: it's unlikely(..) to have to do the write in vm_event_vcpu_enter) Not really. It was mostly to avoid setting/clearing HCR bits in different place in the code. It makes more difficult to know what is the final result of the register. Anyway, let's skip it for now, if it is too difficult. Regards, Then perhaps something like the following would be suitable: 1. store hcr in arch_domain (register_t hcr) 2. add a function in asm-arm/processor.h (or where else?) which only does: static inline void update_hcr(struct domain *d) { WRITE_SYSREG(d->arch.hcr, HCR_EL2); isb(); } 3. modify p2m_restore_state to do: n->domain->arch.hcr &= ~HCR_VM; update_hcr(n->domain); p2m_load_VTTBR(n->domain); n->domain->arch.hcr |= HCR_VM; if ( is_32bit_domain(n->domain) ) n->domain->arch.hcr &= ~HCR_RW; else n->domain->arch.hcr |= HCR_RW; update_hcr(n->domain); WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); 4. and vcpu_enter_adjust_traps to if ( unlikely(0 != v->domain->arch.monitor.write_ctrlreg_enabled) ) { if ( likely(v->domain->arch.hcr & HCR_TVM) ) return; v->domain->arch.hcr |= HCR_TVM; } else { if ( likely(!(v->domain->arch.hcr & HCR_TVM)) ) return; v->domain->arch.hcr &= ~HCR_TVM; } update_hcr(v->domain); That way at least it's easier to follow where update_hcr is called. Corneliu. And also set the initial value of HCR at the moment of creation, i.e. in arch_domain_create as d->arch.hcr = READ_SYSREG(HCR_EL2) Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/22/2016 10:41 PM, Julien Grall wrote: On 22/06/2016 20:37, Corneliu ZUZU wrote: I've also realized that it's a bit complicated to avoid writing HCR from 2 places. That's because: - p2m_restore_state is part of the process of switching to another vCPU and the HCR write _must be committed_ here because other components depend on that, like address-translation functions - I want vm_event_vcpu_enter to be called _after_ the switch to the vCPU is completed - I want HCR_TVM to be set in vm_event_vcpu_enter because setting necessary traps _for cr vm-events_ to work should be done there (setting HCR_TVM bit makes sense to be there and the purpose is to centralize operations such as this for code comprehensibility; also, on the X86 counterpart a similar operation is done for trapping CR3, so it would be nice to keep the symmetry) Would it be such a stretch to have HCR written in 2 places? (the second time happens rarely anyway: it's unlikely(..) to have to do the write in vm_event_vcpu_enter) Not really. It was mostly to avoid setting/clearing HCR bits in different place in the code. It makes more difficult to know what is the final result of the register. Anyway, let's skip it for now, if it is too difficult. Regards, Then perhaps something like the following would be suitable: 1. store hcr in arch_domain (register_t hcr) 2. add a function in asm-arm/processor.h (or where else?) which only does: static inline void update_hcr(struct domain *d) { WRITE_SYSREG(d->arch.hcr, HCR_EL2); isb(); } 3. modify p2m_restore_state to do: n->domain->arch.hcr &= ~HCR_VM; update_hcr(n->domain); p2m_load_VTTBR(n->domain); n->domain->arch.hcr |= HCR_VM; if ( is_32bit_domain(n->domain) ) n->domain->arch.hcr &= ~HCR_RW; else n->domain->arch.hcr |= HCR_RW; update_hcr(n->domain); WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); 4. and vcpu_enter_adjust_traps to if ( unlikely(0 != v->domain->arch.monitor.write_ctrlreg_enabled) ) { if ( likely(v->domain->arch.hcr & HCR_TVM) ) return; v->domain->arch.hcr |= HCR_TVM; } else { if ( likely(!(v->domain->arch.hcr & HCR_TVM)) ) return; v->domain->arch.hcr &= ~HCR_TVM; } update_hcr(v->domain); That way at least it's easier to follow where update_hcr is called. Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 22/06/2016 20:37, Corneliu ZUZU wrote: I've also realized that it's a bit complicated to avoid writing HCR from 2 places. That's because: - p2m_restore_state is part of the process of switching to another vCPU and the HCR write _must be committed_ here because other components depend on that, like address-translation functions - I want vm_event_vcpu_enter to be called _after_ the switch to the vCPU is completed - I want HCR_TVM to be set in vm_event_vcpu_enter because setting necessary traps _for cr vm-events_ to work should be done there (setting HCR_TVM bit makes sense to be there and the purpose is to centralize operations such as this for code comprehensibility; also, on the X86 counterpart a similar operation is done for trapping CR3, so it would be nice to keep the symmetry) Would it be such a stretch to have HCR written in 2 places? (the second time happens rarely anyway: it's unlikely(..) to have to do the write in vm_event_vcpu_enter) Not really. It was mostly to avoid setting/clearing HCR bits in different place in the code. It makes more difficult to know what is the final result of the register. Anyway, let's skip it for now, if it is too difficult. Regards, -- Julien Grall ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/22/2016 9:39 PM, Corneliu ZUZU wrote: On 6/22/2016 8:17 PM, Julien Grall wrote: On 22/06/16 17:35, Corneliu ZUZU wrote: Julien, Hello Corneliu, I was trying to implement having HCR stored in arch_domain or arch_vcpu as suggested above and I'm a bit confused about the code in p2m_restore_state. I'm hoping you can provide some feedback on this matter. Here's the current implementation of the function: void p2m_restore_state(struct vcpu *n) { register_t hcr; hcr = READ_SYSREG(HCR_EL2); WRITE_SYSREG(hcr & ~HCR_VM, HCR_EL2); isb(); p2m_load_VTTBR(n->domain); isb(); if ( is_32bit_domain(n->domain) ) hcr &= ~HCR_RW; else hcr |= HCR_RW; WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); WRITE_SYSREG(hcr, HCR_EL2); isb(); } First of all, I see the HCR_VM bit being unset (=0) but I don't quite understand why and even more peculiar is the fact that I couldn't find any place where the bit is set (=1) again. After the first write to HCR_EL2, "hcr" still have the VM bit set as we only mask it. So the second write will re-set the VM bit. Ooh..right. Don't know how I missed that, I guess I was too focused in finding a -different- place where HCR was modified. I am not sure why the VM bit is unset/set in this function. I am not able to find a paragraph justifying it in the ARM ARM. I have CCed some ARM folks to check if I missed something. An answer to that would be useful. I'm also curious if there's a reason why HCR_RW is set/unset afterwards and not before and why there's an isb() after calling p2m_load_VTTBR if that function already has an isb() @ its end. Secondly, why this order of operations? More specifically, why is p2m_load_VTTBR done after the HCR_VM bit is unset and before the HCR_RW bit is set/unset? Can't we write HCR only once here? And finally, I see the function is called by construct_dom0. The code there looks like: /* * The following loads use the domain's p2m and require current to * be a vcpu of the domain, temporarily switch */ saved_current = current; p2m_restore_state(v); [...] /* Now that we are done restore the original p2m and current. */ set_current(saved_current); p2m_restore_state(saved_current); I suppose the significant changes p2m_restore_state does for the code in between ("[...]") is setting VTTBR & SCTLR which are used by translation functions such as gvirt_to_maddr (which seems to use PAR_EL1). What I don't grasp is what effect setting the VTTBR has if HCR.HCR_VM is unset and left unset... HCR.VM is not left unset (see why above). Regards, Thanks, Corneliu. Julien, I've also realized that it's a bit complicated to avoid writing HCR from 2 places. That's because: - p2m_restore_state is part of the process of switching to another vCPU and the HCR write _must be committed_ here because other components depend on that, like address-translation functions - I want vm_event_vcpu_enter to be called _after_ the switch to the vCPU is completed - I want HCR_TVM to be set in vm_event_vcpu_enter because setting necessary traps _for cr vm-events_ to work should be done there (setting HCR_TVM bit makes sense to be there and the purpose is to centralize operations such as this for code comprehensibility; also, on the X86 counterpart a similar operation is done for trapping CR3, so it would be nice to keep the symmetry) Would it be such a stretch to have HCR written in 2 places? (the second time happens rarely anyway: it's unlikely(..) to have to do the write in vm_event_vcpu_enter) Regards, Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/22/2016 8:17 PM, Julien Grall wrote: On 22/06/16 17:35, Corneliu ZUZU wrote: Julien, Hello Corneliu, I was trying to implement having HCR stored in arch_domain or arch_vcpu as suggested above and I'm a bit confused about the code in p2m_restore_state. I'm hoping you can provide some feedback on this matter. Here's the current implementation of the function: void p2m_restore_state(struct vcpu *n) { register_t hcr; hcr = READ_SYSREG(HCR_EL2); WRITE_SYSREG(hcr & ~HCR_VM, HCR_EL2); isb(); p2m_load_VTTBR(n->domain); isb(); if ( is_32bit_domain(n->domain) ) hcr &= ~HCR_RW; else hcr |= HCR_RW; WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); WRITE_SYSREG(hcr, HCR_EL2); isb(); } First of all, I see the HCR_VM bit being unset (=0) but I don't quite understand why and even more peculiar is the fact that I couldn't find any place where the bit is set (=1) again. After the first write to HCR_EL2, "hcr" still have the VM bit set as we only mask it. So the second write will re-set the VM bit. Ooh..right. Don't know how I missed that, I guess I was too focused in finding a -different- place where HCR was modified. I am not sure why the VM bit is unset/set in this function. I am not able to find a paragraph justifying it in the ARM ARM. I have CCed some ARM folks to check if I missed something. An answer to that would be useful. I'm also curious if there's a reason why HCR_RW is set/unset afterwards and not before and why there's an isb() after calling p2m_load_VTTBR if that function already has an isb() @ its end. Secondly, why this order of operations? More specifically, why is p2m_load_VTTBR done after the HCR_VM bit is unset and before the HCR_RW bit is set/unset? Can't we write HCR only once here? And finally, I see the function is called by construct_dom0. The code there looks like: /* * The following loads use the domain's p2m and require current to * be a vcpu of the domain, temporarily switch */ saved_current = current; p2m_restore_state(v); [...] /* Now that we are done restore the original p2m and current. */ set_current(saved_current); p2m_restore_state(saved_current); I suppose the significant changes p2m_restore_state does for the code in between ("[...]") is setting VTTBR & SCTLR which are used by translation functions such as gvirt_to_maddr (which seems to use PAR_EL1). What I don't grasp is what effect setting the VTTBR has if HCR.HCR_VM is unset and left unset... HCR.VM is not left unset (see why above). Regards, Thanks, Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 22/06/16 17:35, Corneliu ZUZU wrote: Julien, Hello Corneliu, I was trying to implement having HCR stored in arch_domain or arch_vcpu as suggested above and I'm a bit confused about the code in p2m_restore_state. I'm hoping you can provide some feedback on this matter. Here's the current implementation of the function: void p2m_restore_state(struct vcpu *n) { register_t hcr; hcr = READ_SYSREG(HCR_EL2); WRITE_SYSREG(hcr & ~HCR_VM, HCR_EL2); isb(); p2m_load_VTTBR(n->domain); isb(); if ( is_32bit_domain(n->domain) ) hcr &= ~HCR_RW; else hcr |= HCR_RW; WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); WRITE_SYSREG(hcr, HCR_EL2); isb(); } First of all, I see the HCR_VM bit being unset (=0) but I don't quite understand why and even more peculiar is the fact that I couldn't find any place where the bit is set (=1) again. After the first write to HCR_EL2, "hcr" still have the VM bit set as we only mask it. So the second write will re-set the VM bit. I am not sure why the VM bit is unset/set in this function. I am not able to find a paragraph justifying it in the ARM ARM. I have CCed some ARM folks to check if I missed something. Secondly, why this order of operations? More specifically, why is p2m_load_VTTBR done after the HCR_VM bit is unset and before the HCR_RW bit is set/unset? Can't we write HCR only once here? And finally, I see the function is called by construct_dom0. The code there looks like: /* * The following loads use the domain's p2m and require current to * be a vcpu of the domain, temporarily switch */ saved_current = current; p2m_restore_state(v); [...] /* Now that we are done restore the original p2m and current. */ set_current(saved_current); p2m_restore_state(saved_current); I suppose the significant changes p2m_restore_state does for the code in between ("[...]") is setting VTTBR & SCTLR which are used by translation functions such as gvirt_to_maddr (which seems to use PAR_EL1). What I don't grasp is what effect setting the VTTBR has if HCR.HCR_VM is unset and left unset... HCR.VM is not left unset (see why above). Regards, -- Julien Grall ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/17/2016 1:36 PM, Corneliu ZUZU wrote: On 6/16/2016 7:49 PM, Julien Grall wrote: Hello Corneliu, On 16/06/16 15:13, Corneliu ZUZU wrote: +case MWS_TTBCR: +MWS_EMUL(TTBCR); +break; +default: +break; +} + +w->status = MWS_NOWRITE; +} + +static inline void vcpu_enter_adjust_traps(struct vcpu *v) +{ +register_t old_hcr, hcr; + +hcr = (old_hcr = READ_SYSREG(HCR_EL2)); + +if ( unlikely(0 != v->domain->arch.monitor.write_ctrlreg_enabled) ) +hcr |= HCR_TVM; +else +hcr &= ~HCR_TVM; + +if ( unlikely(hcr != old_hcr) ) +{ +WRITE_SYSREG(hcr, HCR_EL2); +isb(); +} The HCR register is also updated in p2m_restore_state to set HCR_EL2.RW. I would prefer to have a single place where HCR is updated. Maybe we should store the HCR value per-domain? Yes, that would be nice. Will look into that for v2. Julien, I was trying to implement having HCR stored in arch_domain or arch_vcpu as suggested above and I'm a bit confused about the code in p2m_restore_state. I'm hoping you can provide some feedback on this matter. Here's the current implementation of the function: void p2m_restore_state(struct vcpu *n) { register_t hcr; hcr = READ_SYSREG(HCR_EL2); WRITE_SYSREG(hcr & ~HCR_VM, HCR_EL2); isb(); p2m_load_VTTBR(n->domain); isb(); if ( is_32bit_domain(n->domain) ) hcr &= ~HCR_RW; else hcr |= HCR_RW; WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); WRITE_SYSREG(hcr, HCR_EL2); isb(); } First of all, I see the HCR_VM bit being unset (=0) but I don't quite understand why and even more peculiar is the fact that I couldn't find any place where the bit is set (=1) again. Secondly, why this order of operations? More specifically, why is p2m_load_VTTBR done after the HCR_VM bit is unset and before the HCR_RW bit is set/unset? Can't we write HCR only once here? And finally, I see the function is called by construct_dom0. The code there looks like: /* * The following loads use the domain's p2m and require current to * be a vcpu of the domain, temporarily switch */ saved_current = current; p2m_restore_state(v); [...] /* Now that we are done restore the original p2m and current. */ set_current(saved_current); p2m_restore_state(saved_current); I suppose the significant changes p2m_restore_state does for the code in between ("[...]") is setting VTTBR & SCTLR which are used by translation functions such as gvirt_to_maddr (which seems to use PAR_EL1). What I don't grasp is what effect setting the VTTBR has if HCR.HCR_VM is unset and left unset... Thanks, Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
Hello Corneliu, On 17/06/16 11:36, Corneliu ZUZU wrote: On 6/16/2016 7:49 PM, Julien Grall wrote: On 16/06/16 15:13, Corneliu ZUZU wrote: [...] Please mention that PRRR and NMRR are aliased to respectively MAIR0 and MAIR1. This will avoid to spend time trying to understanding why the spec says they are trapped but you don't "handle" them. I mentioned that in traps.h (see "AKA" comments). Will put the same comment here then. I noticed it later. But it was not obvious to find. [...] diff --git a/xen/arch/arm/vm_event.c b/xen/arch/arm/vm_event.c new file mode 100644 index 000..3f23fec --- /dev/null +++ b/xen/arch/arm/vm_event.c @@ -0,0 +1,112 @@ [...] +#include +#include + +#if CONFIG_ARM_64 + +#define MWSINF_SCTLR32,SCTLR_EL1 +#define MWSINF_TTBR064,TTBR0_EL1 +#define MWSINF_TTBR164,TTBR1_EL1 +#define MWSINF_TTBCR64,TCR_EL1 + +#elif CONFIG_ARM_32 + +#define MWSINF_SCTLR32,SCTLR +#define MWSINF_TTBR064,TTBR0 +#define MWSINF_TTBR164,TTBR1 The values are the same as for arm64 (*_EL1 is aliased to * for arm32). Please avoid duplication. (see comment below about later reply) Your later reply explain why you did not expose TTBR*_32 to ARM64, but does not explain why the 3 define above is the same as the ARM64. +#define MWSINF_TTBR0_32 32,TTBR0_32 +#define MWSINF_TTBR1_32 32,TTBR1_32 +#define MWSINF_TTBCR32,TTBCR + +#endif + +#define MWS_EMUL_(val, sz, r...) WRITE_SYSREG##sz((uint##sz##_t) (val), r) The cast is not necessary. +#define MWS_EMUL(r) CALL_MACRO(MWS_EMUL_, w->value, MWSINF_##r) + +static inline void vcpu_enter_write_data(struct vcpu *v) +{ +struct monitor_write_data *w = >arch.vm_event.write_data; + +if ( likely(MWS_NOWRITE == w->status) ) +return; + +switch ( w->status ) +{ +case MWS_SCTLR: +MWS_EMUL(SCTLR); +break; +case MWS_TTBR0: +MWS_EMUL(TTBR0); +break; +case MWS_TTBR1: +MWS_EMUL(TTBR1); +break; +#if CONFIG_ARM_32 +case MWS_TTBR0_32: +MWS_EMUL(TTBR0_32); +break; +case MWS_TTBR1_32: +MWS_EMUL(TTBR1_32); +break; +#endif Aarch32 kernel can return on an AArch64 Xen. This means that TTBR{0,1}_32 could be trapped and the write therefore be properly emulated. MCR TTBRx writes from AArch32 guests appear as writes of the low 32-bits of AArch64 TTBRx_EL1 (architecturally mapped). MCRR TTBRx writes from AArch32 guests appear as writes to AArch64 TTBRx_EL1. Therefore, in the end the register we need to write is still TTBRx_EL1. Why would you want to notify write to TTBR*_32 when Xen is running in AArch32 mode and none in Aaarch64 mode? The vm-events for an AArch32 guests should be exactly the same regardless of Xen mode (i.e AArch32 vs AArch64). [...] @@ -0,0 +1,253 @@ [...] +/* + * Emulation of system-register trapped writes that do not cause + * VM_EVENT_REASON_WRITE_CTRLREG monitor vm-events. + * Such writes are collaterally trapped due to setting the HCR_EL2.TVM bit. + * + * Regarding aarch32 domains, note that from Xen's perspective system-registers + * of such domains are architecturally-mapped to aarch64 registers in one of + * three ways: + * - low 32-bits mapping (e.g. aarch32 DFAR -> aarch64 FAR_EL1[31:0]) + * - high 32-bits mapping (e.g. aarch32 IFAR -> aarch64 FAR_EL1[63:32]) + * - full mapping (e.g. aarch32 SCTLR -> aarch64 SCTLR_EL1) + * + * Hence we define 2 macro variants: + * - TVM_EMUL_SZ variant, for full mappings + * - TVM_EMUL_LH variant, for low/high 32-bits mappings + */ +#define TVM_EMUL_SZ(regs, hsr, val, sz, r...) \ +{ \ +if ( psr_mode_is_user(regs) ) \ Those registers are not accessible at EL0. Hmm, I have this question noted. I remember finding from the manuals that a write from user-mode of those regs would still trap to EL2, but I didn't test that yet. Will put that to test and come back with results for v2. Testing will not tell you if a trap will occur or not. The ARM ARM may define it as IMPLEMENTATION DEFINED. From my understanding of the ARMv7 spec (B1.14.1 and B1.14.13 in ARM DDI 0406C.c), the instruction at PL0 (user mode) will not trap to the hypervisor: "Setting HCR.TVM to 1 means that any attempt, to write to a Non-secure memory control register from a Non-secure PL1 or PL0 mode, that this reference manual does not describe as UNDEFINED , generates a Hyp Trap exception." For ARMv8 (See description of HCR_EL2.TVM D7-1971 in ARM DDI 0487A.j), only NS EL1 write to the registers will be trapped. +return inject_undef_exception(regs, hsr); \ +WRITE_SYSREG##sz((uint##sz##_t) (val), r); [...] diff --git a/xen/include/asm-arm/vm_event.h b/xen/include/asm-arm/vm_event.h index 4e5a272..edf9654 100644 --- a/xen/include/asm-arm/vm_event.h +++ b/xen/include/asm-arm/vm_event.h @@ -30,6 +30,12 @@ static inline int
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/17/2016 12:28 AM, Julien Grall wrote: On 16/06/2016 20:24, Corneliu ZUZU wrote: On 6/16/2016 5:26 PM, Julien Grall wrote: Hi Julien. Yes, I agree that it's complex, I would have preferred to split it up too and I actually tried, but the changes are tightly coupled and they don't seem to be 'split-able'. After I reviewed this patch I think it could be simplified a lot. Most of the registers not trapped by vm-event could be emulated with one-line WRITE_SYSREGxx and does not require specific case depending on the architecture. You can give a look how we handle the domain context switch in C (arch/arm/domain.c). Only few of the registers will require more than one-line (such as MAIR*, *FAR) which could be over a macro. Regards, Ok, I'll take a look again but I'm not that optimistic, I remember trying pretty hard to simplify this (and kind of failing), I got the best I could. I think it had to do with the fact the SCTLR macros & such got expanded too early (where I wanted to use them as prefixes to construct other macros). Having said this, I'll look into your suggestions and reinspect the code to recall why those macros got to be the way the are and get back with conclusions. Regards, Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/16/2016 7:49 PM, Julien Grall wrote: Hello Corneliu, On 16/06/16 15:13, Corneliu ZUZU wrote: diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 8c50685..af61ac3 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "decode.h" #include "vtimer.h" @@ -124,7 +125,12 @@ void init_traps(void) WRITE_SYSREG((HCPTR_CP_MASK & ~(HCPTR_CP(10) | HCPTR_CP(11))) | HCPTR_TTA, CPTR_EL2); -/* Setup hypervisor traps */ +/* Setup hypervisor traps + * + * Note: HCR_TVM bit is also set for system-register write monitoring + * purposes (see vm_event_monitor_cr), but (for performance reasons) that's + * done selectively (see vcpu_enter_adjust_traps). + */ WRITE_SYSREG(HCR_PTW|HCR_BSU_INNER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM| HCR_TWE|HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP|HCR_FB, HCR_EL2); @@ -1720,6 +1726,7 @@ static void do_cp15_32(struct cpu_user_regs *regs, const struct hsr_cp32 cp32 = hsr.cp32; int regidx = cp32.reg; struct vcpu *v = current; +register_t r = get_user_reg(regs, regidx); if ( !check_conditional_instr(regs, hsr) ) { @@ -1730,6 +1737,61 @@ static void do_cp15_32(struct cpu_user_regs *regs, switch ( hsr.bits & HSR_CP32_REGS_MASK ) { /* + * HCR_EL2.TVM / HCR.TVM + * + * ARMv7 (DDI 0406C.b): B1.14.13 Please try to mention the most recent spec. This was published in 2012, the latest release (C.c) was published in 2014. Ack. + * ARMv8 (DDI 0487A.e): D1-1569 Table D1-34 Ditto. This was published in 2014, whilst the most recent was published in 2016. + */ +case HSR_CPREG32(SCTLR): +TVM_EMUL_VMEVT(v, regs, hsr, r, SCTLR); +break; +case HSR_CPREG32(TTBR0_32): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBR0_32); +break; +case HSR_CPREG32(TTBR1_32): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBR1_32); +break; +case HSR_CPREG32(TTBCR): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBCR); +break; +case HSR_CPREG32(DACR): +TVM_EMUL(regs, hsr, r, DACR); +break; +case HSR_CPREG32(DFSR): +TVM_EMUL(regs, hsr, r, DFSR); +break; +case HSR_CPREG32(IFSR): +TVM_EMUL(regs, hsr, r, IFSR); +break; +case HSR_CPREG32(DFAR): +TVM_EMUL(regs, hsr, r, DFAR); +break; +case HSR_CPREG32(IFAR): +TVM_EMUL(regs, hsr, r, IFAR); +break; [...] +case HSR_CPREG32(ADFSR): +TVM_EMUL(regs, hsr, r, ADFSR); +break; +case HSR_CPREG32(AIFSR): +TVM_EMUL(regs, hsr, r, AIFSR); +break; +case HSR_CPREG32(MAIR0): +TVM_EMUL(regs, hsr, r, MAIR0); +break; +case HSR_CPREG32(MAIR1): +TVM_EMUL(regs, hsr, r, MAIR1); +break; Please mention that PRRR and NMRR are aliased to respectively MAIR0 and MAIR1. This will avoid to spend time trying to understanding why the spec says they are trapped but you don't "handle" them. I mentioned that in traps.h (see "AKA" comments). Will put the same comment here then. +case HSR_CPREG32(AMAIR0): +TVM_EMUL(regs, hsr, r, AMAIR0); +break; +case HSR_CPREG32(AMAIR1): +TVM_EMUL(regs, hsr, r, AMAIR1); +break; +case HSR_CPREG32(CONTEXTIDR): +TVM_EMUL(regs, hsr, r, CONTEXTIDR); +break; + +/* * !CNTHCTL_EL2.EL1PCEN / !CNTHCTL.PL1PCEN * * ARMv7 (DDI 0406C.b): B4.1.22 @@ -1853,6 +1915,13 @@ static void do_cp15_32(struct cpu_user_regs *regs, static void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr) { +struct vcpu *v = current; +const struct hsr_cp64 cp64 = hsr.cp64; +sysreg64_t r = { +.low32 = (uint32_t) get_user_reg(regs, cp64.reg1), The cast is not necessary. Ack. +.high32 = (uint32_t) get_user_reg(regs, cp64.reg2) Ditto. +}; + if ( !check_conditional_instr(regs, hsr) ) { advance_pc(regs, hsr); @@ -1862,6 +1931,19 @@ static void do_cp15_64(struct cpu_user_regs *regs, switch ( hsr.bits & HSR_CP64_REGS_MASK ) { /* + * HCR_EL2.TVM / HCR.TVM + * + * ARMv7 (DDI 0406C.b): B1.14.13 + * ARMv8 (DDI 0487A.e): D1-1569 Table D1-34 Same remarks as above for the spec version. + */ +case HSR_CPREG64(TTBR0): +TVM_EMUL_VMEVT(v, regs, hsr, r.val64, TTBR0_64); +break; +case HSR_CPREG64(TTBR1): +TVM_EMUL_VMEVT(v, regs, hsr, r.val64, TTBR1_64); +break; + +/* * !CNTHCTL_EL2.EL1PCEN / !CNTHCTL.PL1PCEN * * ARMv7 (DDI 0406C.b): B4.1.22 @@ -1891,8 +1973,6 @@ static void do_cp15_64(struct cpu_user_regs *regs, */ default: { -const struct hsr_cp64 cp64 = hsr.cp64; - gdprintk(XENLOG_ERR, "%s p15, %d,
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 16/06/2016 20:24, Corneliu ZUZU wrote: On 6/16/2016 5:26 PM, Julien Grall wrote: Hi Julien. Yes, I agree that it's complex, I would have preferred to split it up too and I actually tried, but the changes are tightly coupled and they don't seem to be 'split-able'. After I reviewed this patch I think it could be simplified a lot. Most of the registers not trapped by vm-event could be emulated with one-line WRITE_SYSREGxx and does not require specific case depending on the architecture. You can give a look how we handle the domain context switch in C (arch/arm/domain.c). Only few of the registers will require more than one-line (such as MAIR*, *FAR) which could be over a macro. Regards, -- Julien Grall ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
On 6/16/2016 5:26 PM, Julien Grall wrote: Hello Corneliu, On 16/06/16 15:13, Corneliu ZUZU wrote: Add ARM support for control-register write monitoring through the vm-events subsystem. Chosen ARM system control-registers that can be monitored are: - VM_EVENT_ARM_SCTLR: AArch32 SCTLR, AArch64 SCTLR_EL1 - VM_EVENT_ARM_TTBR{0,1}: AArch32 TTBR{0,1}, AArch64 TTBR{0,1}_EL1 - VM_EVENT_ARM_TTBCR: AArch32 TTBCR, AArch64 TCR_EL1 Trapping of write operations of these registers was attained by setting the HCR_EL2.TVM / HCR.TVM bit. Signed-off-by: Corneliu ZUZU--- MAINTAINERS| 1 + xen/arch/arm/Makefile | 1 + xen/arch/arm/traps.c | 126 +++- xen/arch/arm/vm_event.c| 112 ++ xen/common/monitor.c | 2 - xen/common/vm_event.c | 2 - xen/include/asm-arm/domain.h | 30 + xen/include/asm-arm/traps.h| 253 + xen/include/asm-arm/vm_event.h | 22 +++- xen/include/public/vm_event.h | 8 +- xen/include/xen/monitor.h | 2 - xen/include/xen/vm_event.h | 2 - 12 files changed, 543 insertions(+), 18 deletions(-) I think this patch would benefit to be split in multiple patches to ease the review and also describe the infrastructure you have introduced (TVM_* & co). I will review in detail later. Regards, Hi Julien. Yes, I agree that it's complex, I would have preferred to split it up too and I actually tried, but the changes are tightly coupled and they don't seem to be 'split-able'. Corneliu. ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
Hello Corneliu, On 16/06/16 15:13, Corneliu ZUZU wrote: diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 8c50685..af61ac3 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "decode.h" #include "vtimer.h" @@ -124,7 +125,12 @@ void init_traps(void) WRITE_SYSREG((HCPTR_CP_MASK & ~(HCPTR_CP(10) | HCPTR_CP(11))) | HCPTR_TTA, CPTR_EL2); -/* Setup hypervisor traps */ +/* Setup hypervisor traps + * + * Note: HCR_TVM bit is also set for system-register write monitoring + * purposes (see vm_event_monitor_cr), but (for performance reasons) that's + * done selectively (see vcpu_enter_adjust_traps). + */ WRITE_SYSREG(HCR_PTW|HCR_BSU_INNER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM| HCR_TWE|HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP|HCR_FB, HCR_EL2); @@ -1720,6 +1726,7 @@ static void do_cp15_32(struct cpu_user_regs *regs, const struct hsr_cp32 cp32 = hsr.cp32; int regidx = cp32.reg; struct vcpu *v = current; +register_t r = get_user_reg(regs, regidx); if ( !check_conditional_instr(regs, hsr) ) { @@ -1730,6 +1737,61 @@ static void do_cp15_32(struct cpu_user_regs *regs, switch ( hsr.bits & HSR_CP32_REGS_MASK ) { /* + * HCR_EL2.TVM / HCR.TVM + * + * ARMv7 (DDI 0406C.b): B1.14.13 Please try to mention the most recent spec. This was published in 2012, the latest release (C.c) was published in 2014. + * ARMv8 (DDI 0487A.e): D1-1569 Table D1-34 Ditto. This was published in 2014, whilst the most recent was published in 2016. + */ +case HSR_CPREG32(SCTLR): +TVM_EMUL_VMEVT(v, regs, hsr, r, SCTLR); +break; +case HSR_CPREG32(TTBR0_32): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBR0_32); +break; +case HSR_CPREG32(TTBR1_32): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBR1_32); +break; +case HSR_CPREG32(TTBCR): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBCR); +break; +case HSR_CPREG32(DACR): +TVM_EMUL(regs, hsr, r, DACR); +break; +case HSR_CPREG32(DFSR): +TVM_EMUL(regs, hsr, r, DFSR); +break; +case HSR_CPREG32(IFSR): +TVM_EMUL(regs, hsr, r, IFSR); +break; +case HSR_CPREG32(DFAR): +TVM_EMUL(regs, hsr, r, DFAR); +break; +case HSR_CPREG32(IFAR): +TVM_EMUL(regs, hsr, r, IFAR); +break; [...] +case HSR_CPREG32(ADFSR): +TVM_EMUL(regs, hsr, r, ADFSR); +break; +case HSR_CPREG32(AIFSR): +TVM_EMUL(regs, hsr, r, AIFSR); +break; +case HSR_CPREG32(MAIR0): +TVM_EMUL(regs, hsr, r, MAIR0); +break; +case HSR_CPREG32(MAIR1): +TVM_EMUL(regs, hsr, r, MAIR1); +break; Please mention that PRRR and NMRR are aliased to respectively MAIR0 and MAIR1. This will avoid to spend time trying to understanding why the spec says they are trapped but you don't "handle" them. +case HSR_CPREG32(AMAIR0): +TVM_EMUL(regs, hsr, r, AMAIR0); +break; +case HSR_CPREG32(AMAIR1): +TVM_EMUL(regs, hsr, r, AMAIR1); +break; +case HSR_CPREG32(CONTEXTIDR): +TVM_EMUL(regs, hsr, r, CONTEXTIDR); +break; + +/* * !CNTHCTL_EL2.EL1PCEN / !CNTHCTL.PL1PCEN * * ARMv7 (DDI 0406C.b): B4.1.22 @@ -1853,6 +1915,13 @@ static void do_cp15_32(struct cpu_user_regs *regs, static void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr) { +struct vcpu *v = current; +const struct hsr_cp64 cp64 = hsr.cp64; +sysreg64_t r = { +.low32 = (uint32_t) get_user_reg(regs, cp64.reg1), The cast is not necessary. +.high32 = (uint32_t) get_user_reg(regs, cp64.reg2) Ditto. +}; + if ( !check_conditional_instr(regs, hsr) ) { advance_pc(regs, hsr); @@ -1862,6 +1931,19 @@ static void do_cp15_64(struct cpu_user_regs *regs, switch ( hsr.bits & HSR_CP64_REGS_MASK ) { /* + * HCR_EL2.TVM / HCR.TVM + * + * ARMv7 (DDI 0406C.b): B1.14.13 + * ARMv8 (DDI 0487A.e): D1-1569 Table D1-34 Same remarks as above for the spec version. + */ +case HSR_CPREG64(TTBR0): +TVM_EMUL_VMEVT(v, regs, hsr, r.val64, TTBR0_64); +break; +case HSR_CPREG64(TTBR1): +TVM_EMUL_VMEVT(v, regs, hsr, r.val64, TTBR1_64); +break; + +/* * !CNTHCTL_EL2.EL1PCEN / !CNTHCTL.PL1PCEN * * ARMv7 (DDI 0406C.b): B4.1.22 @@ -1891,8 +1973,6 @@ static void do_cp15_64(struct cpu_user_regs *regs, */ default: { -const struct hsr_cp64 cp64 = hsr.cp64; - gdprintk(XENLOG_ERR, "%s p15, %d, r%d, r%d, cr%d @ 0x%"PRIregister"\n", cp64.read ? "mrrc" : "mcrr", @@ -2128,10 +2208,50 @@ static void
Re: [Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
Hello Corneliu, On 16/06/16 15:13, Corneliu ZUZU wrote: Add ARM support for control-register write monitoring through the vm-events subsystem. Chosen ARM system control-registers that can be monitored are: - VM_EVENT_ARM_SCTLR: AArch32 SCTLR, AArch64 SCTLR_EL1 - VM_EVENT_ARM_TTBR{0,1}: AArch32 TTBR{0,1}, AArch64 TTBR{0,1}_EL1 - VM_EVENT_ARM_TTBCR: AArch32 TTBCR, AArch64 TCR_EL1 Trapping of write operations of these registers was attained by setting the HCR_EL2.TVM / HCR.TVM bit. Signed-off-by: Corneliu ZUZU--- MAINTAINERS| 1 + xen/arch/arm/Makefile | 1 + xen/arch/arm/traps.c | 126 +++- xen/arch/arm/vm_event.c| 112 ++ xen/common/monitor.c | 2 - xen/common/vm_event.c | 2 - xen/include/asm-arm/domain.h | 30 + xen/include/asm-arm/traps.h| 253 + xen/include/asm-arm/vm_event.h | 22 +++- xen/include/public/vm_event.h | 8 +- xen/include/xen/monitor.h | 2 - xen/include/xen/vm_event.h | 2 - 12 files changed, 543 insertions(+), 18 deletions(-) I think this patch would benefit to be split in multiple patches to ease the review and also describe the infrastructure you have introduced (TVM_* & co). I will review in detail later. Regards, -- Julien Grall ___ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
[Xen-devel] [PATCH 7/7] vm-event/arm: implement support for control-register write vm-events
Add ARM support for control-register write monitoring through the vm-events subsystem. Chosen ARM system control-registers that can be monitored are: - VM_EVENT_ARM_SCTLR: AArch32 SCTLR, AArch64 SCTLR_EL1 - VM_EVENT_ARM_TTBR{0,1}: AArch32 TTBR{0,1}, AArch64 TTBR{0,1}_EL1 - VM_EVENT_ARM_TTBCR: AArch32 TTBCR, AArch64 TCR_EL1 Trapping of write operations of these registers was attained by setting the HCR_EL2.TVM / HCR.TVM bit. Signed-off-by: Corneliu ZUZU--- MAINTAINERS| 1 + xen/arch/arm/Makefile | 1 + xen/arch/arm/traps.c | 126 +++- xen/arch/arm/vm_event.c| 112 ++ xen/common/monitor.c | 2 - xen/common/vm_event.c | 2 - xen/include/asm-arm/domain.h | 30 + xen/include/asm-arm/traps.h| 253 + xen/include/asm-arm/vm_event.h | 22 +++- xen/include/public/vm_event.h | 8 +- xen/include/xen/monitor.h | 2 - xen/include/xen/vm_event.h | 2 - 12 files changed, 543 insertions(+), 18 deletions(-) create mode 100644 xen/arch/arm/vm_event.c create mode 100644 xen/include/asm-arm/traps.h diff --git a/MAINTAINERS b/MAINTAINERS index 9a224d4..634f359 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -402,6 +402,7 @@ M: Tamas K Lengyel S: Supported F: xen/common/mem_access.c F: xen/*/vm_event.c +F: xen/arch/*/vm_event.c F: xen/*/monitor.c F: xen/include/*/mem_access.h F: xen/include/*/monitor.h diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 9e38da3..390df0a 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -40,6 +40,7 @@ obj-y += device.o obj-y += decode.o obj-y += processor.o obj-y += smc.o +obj-y += vm_event.o obj-$(CONFIG_LIVEPATCH) += livepatch.o #obj-bin-y += o diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 8c50685..af61ac3 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "decode.h" #include "vtimer.h" @@ -124,7 +125,12 @@ void init_traps(void) WRITE_SYSREG((HCPTR_CP_MASK & ~(HCPTR_CP(10) | HCPTR_CP(11))) | HCPTR_TTA, CPTR_EL2); -/* Setup hypervisor traps */ +/* Setup hypervisor traps + * + * Note: HCR_TVM bit is also set for system-register write monitoring + * purposes (see vm_event_monitor_cr), but (for performance reasons) that's + * done selectively (see vcpu_enter_adjust_traps). + */ WRITE_SYSREG(HCR_PTW|HCR_BSU_INNER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM| HCR_TWE|HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP|HCR_FB, HCR_EL2); @@ -1720,6 +1726,7 @@ static void do_cp15_32(struct cpu_user_regs *regs, const struct hsr_cp32 cp32 = hsr.cp32; int regidx = cp32.reg; struct vcpu *v = current; +register_t r = get_user_reg(regs, regidx); if ( !check_conditional_instr(regs, hsr) ) { @@ -1730,6 +1737,61 @@ static void do_cp15_32(struct cpu_user_regs *regs, switch ( hsr.bits & HSR_CP32_REGS_MASK ) { /* + * HCR_EL2.TVM / HCR.TVM + * + * ARMv7 (DDI 0406C.b): B1.14.13 + * ARMv8 (DDI 0487A.e): D1-1569 Table D1-34 + */ +case HSR_CPREG32(SCTLR): +TVM_EMUL_VMEVT(v, regs, hsr, r, SCTLR); +break; +case HSR_CPREG32(TTBR0_32): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBR0_32); +break; +case HSR_CPREG32(TTBR1_32): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBR1_32); +break; +case HSR_CPREG32(TTBCR): +TVM_EMUL_VMEVT(v, regs, hsr, r, TTBCR); +break; +case HSR_CPREG32(DACR): +TVM_EMUL(regs, hsr, r, DACR); +break; +case HSR_CPREG32(DFSR): +TVM_EMUL(regs, hsr, r, DFSR); +break; +case HSR_CPREG32(IFSR): +TVM_EMUL(regs, hsr, r, IFSR); +break; +case HSR_CPREG32(DFAR): +TVM_EMUL(regs, hsr, r, DFAR); +break; +case HSR_CPREG32(IFAR): +TVM_EMUL(regs, hsr, r, IFAR); +break; +case HSR_CPREG32(ADFSR): +TVM_EMUL(regs, hsr, r, ADFSR); +break; +case HSR_CPREG32(AIFSR): +TVM_EMUL(regs, hsr, r, AIFSR); +break; +case HSR_CPREG32(MAIR0): +TVM_EMUL(regs, hsr, r, MAIR0); +break; +case HSR_CPREG32(MAIR1): +TVM_EMUL(regs, hsr, r, MAIR1); +break; +case HSR_CPREG32(AMAIR0): +TVM_EMUL(regs, hsr, r, AMAIR0); +break; +case HSR_CPREG32(AMAIR1): +TVM_EMUL(regs, hsr, r, AMAIR1); +break; +case HSR_CPREG32(CONTEXTIDR): +TVM_EMUL(regs, hsr, r, CONTEXTIDR); +break; + +/* * !CNTHCTL_EL2.EL1PCEN / !CNTHCTL.PL1PCEN * * ARMv7 (DDI 0406C.b): B4.1.22 @@ -1853,6 +1915,13 @@ static void do_cp15_32(struct cpu_user_regs *regs, static void do_cp15_64(struct cpu_user_regs *regs,