[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [PATCH v5 08/20] intc/arm_gic: Refactor secure/ns access
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [Qemu-arm] [PATCH v5 08/20] intc/arm_gic: Refactor secure/ns access check in the CPU interface |
Date: |
Fri, 27 Jul 2018 09:45:16 -0300 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 |
On 07/27/2018 06:54 AM, Luc Michel wrote:
> An access to the CPU interface is non-secure if the current GIC instance
> implements the security extensions, and the memory access is actually
> non-secure. Until then, it was checked with tests such as
> if (s->security_extn && !attrs.secure) { ... }
> in various places of the CPU interface code.
>
> With the implementation of the virtualization extensions, those tests
> must be updated to take into account whether we are in a vCPU interface
> or not. This is because the exposed vCPU interface does not implement
> security extensions.
>
> This commits replaces all those tests with a call to the
> gic_cpu_ns_access() function to check if the current access to the CPU
> interface is non-secure. This function takes into account whether the
> current CPU is a vCPU or not.
>
> Note that this function is used only in the (v)CPU interface code path.
> The distributor code path is left unchanged, as the distributor is not
> exposed to vCPUs at all.
>
> Signed-off-by: Luc Michel <address@hidden>
> Reviewed-by: Peter Maydell <address@hidden>
> ---
> hw/intc/arm_gic.c | 39 ++++++++++++++++++++++-----------------
> 1 file changed, 22 insertions(+), 17 deletions(-)
>
> diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
> index 41141fee53..94d5982e2a 100644
> --- a/hw/intc/arm_gic.c
> +++ b/hw/intc/arm_gic.c
> @@ -72,10 +72,15 @@ static inline int gic_get_current_vcpu(GICState *s)
> static inline bool gic_has_groups(GICState *s)
> {
> return s->revision == 2 || s->security_extn;
> }
>
> +static inline bool gic_cpu_ns_access(GICState *s, int cpu, MemTxAttrs attrs)
> +{
> + return !gic_is_vcpu(cpu) && s->security_extn && !attrs.secure;
> +}
> +
> /* TODO: Many places that call this routine could be optimized. */
> /* Update interrupt status after enabled or pending bits have been changed.
> */
> static void gic_update(GICState *s)
> {
> int best_irq;
> @@ -219,11 +224,11 @@ static uint16_t gic_get_current_pending_irq(GICState
> *s, int cpu,
> if (pending_irq < GIC_MAXIRQ && gic_has_groups(s)) {
> int group = GIC_DIST_TEST_GROUP(pending_irq, (1 << cpu));
> /* On a GIC without the security extensions, reading this register
> * behaves in the same way as a secure access to a GIC with them.
> */
> - bool secure = !s->security_extn || attrs.secure;
> + bool secure = !gic_cpu_ns_access(s, cpu, attrs);
>
> if (group == 0 && !secure) {
> /* Group0 interrupts hidden from Non-secure access */
> return 1023;
> }
> @@ -426,11 +431,11 @@ static uint32_t gic_dist_get_priority(GICState *s, int
> cpu, int irq,
> }
>
> static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask,
> MemTxAttrs attrs)
> {
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> if (s->priority_mask[cpu] & 0x80) {
> /* Priority Mask in upper half */
> pmask = 0x80 | (pmask >> 1);
> } else {
> /* Non-secure write ignored if priority mask is in lower half */
> @@ -442,11 +447,11 @@ static void gic_set_priority_mask(GICState *s, int cpu,
> uint8_t pmask,
>
> static uint32_t gic_get_priority_mask(GICState *s, int cpu, MemTxAttrs attrs)
> {
> uint32_t pmask = s->priority_mask[cpu];
>
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> if (pmask & 0x80) {
> /* Priority Mask in upper half, return Non-secure view */
> pmask = (pmask << 1) & 0xff;
> } else {
> /* Priority Mask in lower half, RAZ */
> @@ -458,11 +463,11 @@ static uint32_t gic_get_priority_mask(GICState *s, int
> cpu, MemTxAttrs attrs)
>
> static uint32_t gic_get_cpu_control(GICState *s, int cpu, MemTxAttrs attrs)
> {
> uint32_t ret = s->cpu_ctlr[cpu];
>
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> /* Construct the NS banked view of GICC_CTLR from the correct
> * bits of the S banked view. We don't need to move the bypass
> * control bits because we don't implement that (IMPDEF) part
> * of the GIC architecture.
> */
> @@ -474,11 +479,11 @@ static uint32_t gic_get_cpu_control(GICState *s, int
> cpu, MemTxAttrs attrs)
> static void gic_set_cpu_control(GICState *s, int cpu, uint32_t value,
> MemTxAttrs attrs)
> {
> uint32_t mask;
>
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> /* The NS view can only write certain bits in the register;
> * the rest are unchanged
> */
> mask = GICC_CTLR_EN_GRP1;
> if (s->revision == 2) {
> @@ -505,11 +510,11 @@ static uint8_t gic_get_running_priority(GICState *s,
> int cpu, MemTxAttrs attrs)
> if ((s->revision != REV_11MPCORE) && (s->running_priority[cpu] > 0xff)) {
> /* Idle priority */
> return 0xff;
> }
>
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> if (s->running_priority[cpu] & 0x80) {
> /* Running priority in upper half of range: return the Non-secure
> * view of the priority.
> */
> return s->running_priority[cpu] << 1;
> @@ -529,11 +534,11 @@ static bool gic_eoi_split(GICState *s, int cpu,
> MemTxAttrs attrs)
> {
> if (s->revision != 2) {
> /* Before GICv2 prio-drop and deactivate are not separable */
> return false;
> }
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE_NS;
> }
> return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE;
> }
>
> @@ -561,11 +566,11 @@ static void gic_deactivate_irq(GICState *s, int cpu,
> int irq, MemTxAttrs attrs)
> qemu_log_mask(LOG_GUEST_ERROR,
> "gic_deactivate_irq: GICC_DIR write when EOIMode
> clear");
> return;
> }
>
> - if (s->security_extn && !attrs.secure && !group) {
> + if (gic_cpu_ns_access(s, cpu, attrs) && !group) {
> DPRINTF("Non-secure DI for Group0 interrupt %d ignored\n", irq);
> return;
> }
>
> GIC_DIST_CLEAR_ACTIVE(irq, cm);
> @@ -603,11 +608,11 @@ static void gic_complete_irq(GICState *s, int cpu, int
> irq, MemTxAttrs attrs)
> }
> }
>
> group = gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, cm);
>
> - if (s->security_extn && !attrs.secure && !group) {
> + if (gic_cpu_ns_access(s, cpu, attrs) && !group) {
> DPRINTF("Non-secure EOI for Group0 interrupt %d ignored\n", irq);
> return;
> }
>
> /* Secure EOI with GICC_CTLR.AckCtl == 0 when the IRQ is a Group 1
> @@ -1279,11 +1284,11 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu,
> int offset,
> break;
> case 0x04: /* Priority mask */
> *data = gic_get_priority_mask(s, cpu, attrs);
> break;
> case 0x08: /* Binary Point */
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
> /* NS view of BPR when CBPR is 1 */
> *data = MIN(s->bpr[cpu] + 1, 7);
> } else {
> /* BPR is banked. Non-secure copy stored in ABPR. */
> @@ -1306,11 +1311,11 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu,
> int offset,
> /* GIC v2, no security: ABPR
> * GIC v1, no security: not implemented (RAZ/WI)
> * With security extensions, secure access: ABPR (alias of NS BPR)
> * With security extensions, nonsecure access: RAZ/WI
> */
> - if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
> + if (!gic_has_groups(s) || (gic_cpu_ns_access(s, cpu, attrs))) {
Superfluous parenthesis,
> *data = 0;
> } else {
> *data = s->abpr[cpu];
> }
> break;
> @@ -1318,11 +1323,11 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu,
> int offset,
> {
> int regno = (offset - 0xd0) / 4;
>
> if (regno >= GIC_NR_APRS || s->revision != 2) {
> *data = 0;
> - } else if (s->security_extn && !attrs.secure) {
> + } else if (gic_cpu_ns_access(s, cpu, attrs)) {
> /* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
> *data = gic_apr_ns_view(s, regno, cpu);
> } else {
> *data = s->apr[regno][cpu];
> }
> @@ -1331,11 +1336,11 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu,
> int offset,
> case 0xe0: case 0xe4: case 0xe8: case 0xec:
> {
> int regno = (offset - 0xe0) / 4;
>
> if (regno >= GIC_NR_APRS || s->revision != 2 || !gic_has_groups(s) ||
> - (s->security_extn && !attrs.secure)) {
> + gic_cpu_ns_access(s, cpu, attrs)) {
> *data = 0;
> } else {
> *data = s->nsapr[regno][cpu];
> }
> break;
> @@ -1358,11 +1363,11 @@ static MemTxResult gic_cpu_write(GICState *s, int
> cpu, int offset,
> break;
> case 0x04: /* Priority mask */
> gic_set_priority_mask(s, cpu, value, attrs);
> break;
> case 0x08: /* Binary Point */
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
> /* WI when CBPR is 1 */
> return MEMTX_OK;
> } else {
> s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);
> @@ -1373,11 +1378,11 @@ static MemTxResult gic_cpu_write(GICState *s, int
> cpu, int offset,
> break;
> case 0x10: /* End Of Interrupt */
> gic_complete_irq(s, cpu, value & 0x3ff, attrs);
> return MEMTX_OK;
> case 0x1c: /* Aliased Binary Point */
> - if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
> + if (!gic_has_groups(s) || (gic_cpu_ns_access(s, cpu, attrs))) {
Ditto,
> /* unimplemented, or NS access: RAZ/WI */
> return MEMTX_OK;
> } else {
> s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);
> }
> @@ -1387,11 +1392,11 @@ static MemTxResult gic_cpu_write(GICState *s, int
> cpu, int offset,
> int regno = (offset - 0xd0) / 4;
>
> if (regno >= GIC_NR_APRS || s->revision != 2) {
> return MEMTX_OK;
> }
> - if (s->security_extn && !attrs.secure) {
> + if (gic_cpu_ns_access(s, cpu, attrs)) {
> /* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
> gic_apr_write_ns_view(s, regno, cpu, value);
> } else {
> s->apr[regno][cpu] = value;
> }
> @@ -1402,11 +1407,11 @@ static MemTxResult gic_cpu_write(GICState *s, int
> cpu, int offset,
> int regno = (offset - 0xe0) / 4;
>
> if (regno >= GIC_NR_APRS || s->revision != 2) {
> return MEMTX_OK;
> }
> - if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
> + if (!gic_has_groups(s) || (gic_cpu_ns_access(s, cpu, attrs))) {
Ditto.
> return MEMTX_OK;
> }
> s->nsapr[regno][cpu] = value;
> break;
> }
>
Reviewed-by: Philippe Mathieu-Daudé <address@hidden>
- [Qemu-arm] [PATCH v5 00/20] arm_gic: add virtualization extensions support, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 02/20] intc/arm_gic: Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 04/20] vmstate.h: Provide VMSTATE_UINT16_SUB_ARRAY, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 12/20] intc/arm_gic: Implement virtualization extensions in gic_(deactivate|complete_irq), Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 03/20] intc/arm_gic: Remove some dead code and put some functions static, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 08/20] intc/arm_gic: Refactor secure/ns access check in the CPU interface, Luc Michel, 2018/07/27
- Re: [Qemu-arm] [PATCH v5 08/20] intc/arm_gic: Refactor secure/ns access check in the CPU interface,
Philippe Mathieu-Daudé <=
- [Qemu-arm] [PATCH v5 06/20] intc/arm_gic: Add virtual interface register definitions, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 13/20] intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write), Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 14/20] intc/arm_gic: Wire the vCPU interface, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 18/20] intc/arm_gic: Improve traces, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 17/20] intc/arm_gic: Implement maintenance interrupt generation, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 20/20] arm/virt: Add support for GICv2 virtualization extensions, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 19/20] xlnx-zynqmp: Improve GIC wiring and MMIO mapping, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 10/20] intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio), Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 16/20] intc/arm_gic: Implement gic_update_virt() function, Luc Michel, 2018/07/27