From 0cdc13fa0e556b527c7672d3c3bb23d07119e7a0 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 15 Feb 2019 11:56:31 +0800 Subject: [PATCH] hv: extend the AC bit of rflags operations for smap For apl_sdc_stable branch, we now have stac and clac to set and clear AC bit of rflags. But it can't handle following sequence: stac stac clac user mode address access here will trigger page fault clac This patch introduce two more functions: - stac_save: Save the rflags and set AC bit - ac_restore: Restore the AC bit saved to rflags Now, only sbuf_put/get are using these new APIs. Tracked-On: #2525 Signed-off-by: Yin Fengwei --- hypervisor/debug/sbuf.c | 14 ++++++++------ hypervisor/include/arch/x86/cpu.h | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/hypervisor/debug/sbuf.c b/hypervisor/debug/sbuf.c index 72527d345..e03fb9a0d 100644 --- a/hypervisor/debug/sbuf.c +++ b/hypervisor/debug/sbuf.c @@ -29,10 +29,11 @@ uint32_t sbuf_get(struct shared_buf *sbuf, uint8_t *data) { const void *from; uint32_t ele_size; + uint64_t rflags; - stac(); + stac_save(&rflags); if (sbuf_is_empty(sbuf)) { - clac(); + ac_restore(&rflags); /* no data available */ return 0; } @@ -44,7 +45,7 @@ uint32_t sbuf_get(struct shared_buf *sbuf, uint8_t *data) sbuf->head = sbuf_next_ptr(sbuf->head, sbuf->ele_size, sbuf->size); ele_size = sbuf->ele_size; - clac(); + ac_restore(&rflags); return ele_size; } @@ -72,9 +73,10 @@ uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data) void *to; uint32_t next_tail; uint32_t ele_size; + uint64_t rflags; bool trigger_overwrite = false; - stac(); + stac_save(&rflags); next_tail = sbuf_next_ptr(sbuf->tail, sbuf->ele_size, sbuf->size); /* if this write would trigger overrun */ if (next_tail == sbuf->head) { @@ -82,7 +84,7 @@ uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data) sbuf->overrun_cnt += sbuf->flags & OVERRUN_CNT_EN; if ((sbuf->flags & OVERWRITE_EN) == 0U) { /* if not enable over write, return here. */ - clac(); + ac_restore(&rflags); return 0; } trigger_overwrite = true; @@ -99,7 +101,7 @@ uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data) sbuf->tail = next_tail; ele_size = sbuf->ele_size; - clac(); + ac_restore(&rflags); return ele_size; } diff --git a/hypervisor/include/arch/x86/cpu.h b/hypervisor/include/arch/x86/cpu.h index e22818374..0e3cc310b 100644 --- a/hypervisor/include/arch/x86/cpu.h +++ b/hypervisor/include/arch/x86/cpu.h @@ -83,6 +83,9 @@ #define CR4_SMAP (1UL<<21U) #define CR4_PKE (1UL<<22U) /* Protect-key-enable */ +#define RFLAGS_C (1U<<0U) +#define RFLAGS_Z (1U<<6U) +#define RFLAGS_AC (1U<<18U) /* * Entries in the Interrupt Descriptor Table (IDT) @@ -542,6 +545,23 @@ static inline void clac(void) asm volatile ("clac" : : : "memory"); } +/* Save rflags register and set AC bit */ +static inline void stac_save(uint64_t *p_rflags) +{ + CPU_RFLAGS_SAVE(p_rflags); + asm volatile ("stac" : : : "memory"); +} + +/* Restore AC bit saved in p_rflags */ +static inline void ac_restore(uint64_t *p_rflags) +{ + if (*p_rflags & RFLAGS_AC) { + stac(); + } else { + clac(); + } +} + #else /* ASSEMBLER defined */ #endif /* ASSEMBLER defined */