[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [PATCH v3 10/43] arm64: add exception support



On Wed, Apr 18, 2018 at 06:48:24PM +0100, Julien Grall wrote:
> Hi Shijie,
> 
> On 16/04/18 07:31, Huang Shijie wrote:
> >This patch adds the exception support for arm64:
> >     .0) Add arm64/traps.h, and add new pt_regs{} for arm64.
> >     .1) Add save_registers/restore_registers which are based on FreeBSD 
> > code.
> 
> Please give a pointer to the code.
okay.
> 
> >     .2) setup the vector table
> >     .3) remove the code for arm32.
> 
> This does not make sense in a patch that is adding arm64 support. The code
> removed look fairly independent, so can you move that in #2.
okay.
> 
> >
> >Signed-off-by: Huang Shijie <shijie.huang@xxxxxxx>
> >---
> >  arch/arm/arm64/arm64.S    | 147 
> > ++++++++++++++++++++++++++++++++++++++++++++++
> >  arch/arm/arm64/traps.c    |  16 +++++
> >  include/arm/arm64/traps.h |  27 +++++++++
> >  include/arm/traps.h       |  21 +------
> >  4 files changed, 191 insertions(+), 20 deletions(-)
> >  create mode 100644 arch/arm/arm64/traps.c
> >  create mode 100644 include/arm/arm64/traps.h
> >
> >diff --git a/arch/arm/arm64/arm64.S b/arch/arm/arm64/arm64.S
> >index b454cc6..9eb7ea0 100644
> >--- a/arch/arm/arm64/arm64.S
> >+++ b/arch/arm/arm64/arm64.S
> >@@ -1,6 +1,7 @@
> >  #include "asm.h"
> >  #include <arch_limits.h>
> >  #include <arm64/pagetable.h>
> >+#include <arm64/traps.h>
> >  #include <xen/xen.h>
> >  /* This macro will use the x0/x1/x2/x16 */
> >@@ -101,6 +102,11 @@ ENTRY(_start)
> >      msr     ttbr0_el1, x0
> >      isb
> >+    /* Load the exception vectors */
> >+    ldr     x2, =vector_table
> >+    msr     vbar_el1, x2
> >+    isb
> 
> I don't think the isb is necessary here. You can rely on the one below (when
> setting up the SCTLR).
> 
> This would be fine because the vector table contains virtual address so it
> is unusable before turning on the MMU.
> 
okay, I will think about it.
> >+
> >      /* Turning on MMU */
> >      tlbi    vmalle1
> >      dsb     nsh
> >@@ -284,3 +290,144 @@ _setup_idmap_pgtable:
> >      adr     x0, idmap_l0_pgtable
> >      dsb     sy
> >      ret
> >+
> >+/* The save_registers/restore_registers are based on the code in FreeBSD */
> 
> Missing full stop.
> 
> >+.macro      save_registers el
> 
> All the code below is using hard tab, however the rest of the file is using
> soft tab. Please replace all hard tab with soft tab.
I will change it to soft tab.
> 
> >+    mov     x18, sp
> 
> Something is wrong here. You seem to overwrite x18 without saving it. Did I
> miss anything?
I copied from the freebsd code. The original code uses x18 here.

It is really not proper to overwrite x18.

I will change it later.

> 
> >+
> >+    sub     sp, sp, #(PT_REG_SIZE)
> >+
> >+    stp     x28, x29, [sp, #(PT_REG_X + 28 * 8)]
> 
> I might be nice to make PT_REG_X a macro take the registers in parameters.
> This would ease the reading of the code.
okay, no problem.

> 
> >+    stp     x26, x27, [sp, #(PT_REG_X + 26 * 8)]
> >+    stp     x24, x25, [sp, #(PT_REG_X + 24 * 8)]
> >+    stp     x22, x23, [sp, #(PT_REG_X + 22 * 8)]
> >+    stp     x20, x21, [sp, #(PT_REG_X + 20 * 8)]
> >+    stp     x18, x19, [sp, #(PT_REG_X + 18 * 8)]
> >+    stp     x16, x17, [sp, #(PT_REG_X + 16 * 8)]
> >+    stp     x14, x15, [sp, #(PT_REG_X + 14 * 8)]
> >+    stp     x12, x13, [sp, #(PT_REG_X + 12 * 8)]
> >+    stp     x10, x11, [sp, #(PT_REG_X + 10 * 8)]
> >+    stp     x8,  x9,  [sp, #(PT_REG_X + 8  * 8)]
> >+    stp     x6,  x7,  [sp, #(PT_REG_X + 6  * 8)]
> >+    stp     x4,  x5,  [sp, #(PT_REG_X + 4  * 8)]
> >+    stp     x2,  x3,  [sp, #(PT_REG_X + 2  * 8)]
> >+    stp     x0,  x1,  [sp, #(PT_REG_X + 0  * 8)]
> >+
> >+    mrs     x10, elr_el1
> >+    mrs     x11, spsr_el1
> >+    mrs     x12, esr_el1
> >+.if \el == 0
> 
> AFAICT you will never go in EL0. So is there any reason to handle EL0?
there is invalid case for EL0, such as el0_irq.
So keep it here for them.

> 
> >+    mrs     x18, sp_el0
> >+.endif
> 
> Hmm I think you want the "mov x18, sp" but you also need to add the
> PT_REG_SIZE to get the correct sp.
The sp is correct here.
We have sub the PT_REG_SIZE at the beginning of the @save_registers.
> 
> >+    str     x10, [sp, #(PT_REG_ELR)]
> >+    stp     w11, w12, [sp, #(PT_REG_SPSR)]
> >+    stp     x18, x30, [sp, #(PT_REG_SP)]
> >+.endm
> >+
> >+.macro      restore_registers el
> 
> Will you ever reach this macro with interrupt enabled? If so, don't you want
> to disable them. So you don't get interrupt in the middle of the restore?
The interrupt is disabled here.


> 
> >+    ldp     x18, x30, [sp, #(PT_REG_SP)]
> >+    ldp     x10, x11, [sp, #(PT_REG_ELR)]
> >+.if \el == 0
> >+    msr     sp_el0, x18
> >+.endif
> >+    msr     spsr_el1, x11
> >+    msr     elr_el1, x10
> >+
> >+    ldp     x0,  x1,  [sp, #(PT_REG_X + 0  * 8)]
> >+    ldp     x2,  x3,  [sp, #(PT_REG_X + 2  * 8)]
> >+    ldp     x4,  x5,  [sp, #(PT_REG_X + 4  * 8)]
> >+    ldp     x6,  x7,  [sp, #(PT_REG_X + 6  * 8)]
> >+    ldp     x8,  x9,  [sp, #(PT_REG_X + 8  * 8)]
> >+    ldp     x10, x11, [sp, #(PT_REG_X + 10 * 8)]
> >+    ldp     x12, x13, [sp, #(PT_REG_X + 12 * 8)]
> >+    ldp     x14, x15, [sp, #(PT_REG_X + 14 * 8)]
> >+    ldp     x16, x17, [sp, #(PT_REG_X + 16 * 8)]
> >+    ldp     x18, x19, [sp, #(PT_REG_X + 18 * 8)]
> >+    ldp     x20, x21, [sp, #(PT_REG_X + 20 * 8)]
> >+    ldp     x22, x23, [sp, #(PT_REG_X + 22 * 8)]
> >+    ldp     x24, x25, [sp, #(PT_REG_X + 24 * 8)]
> >+    ldp     x26, x27, [sp, #(PT_REG_X + 26 * 8)]
> >+    ldp     x28, x29, [sp, #(PT_REG_X + 28 * 8)]
> >+
> >+    mov     sp, x18
> 
> So x18 will not contain the sp here. But I think adding PT_REG_SIZE to sp
> should be enough here.
the x18 stores the previous sp maybe is different with current sp, 
 So add PT_REG_SIZE to sp is wrong.   
> 
> >+        eret
> >+.endm
> >+
> >+    .globl IRQ_handler
> >+IRQ_handler:
> >+    .long 0x0
> 
> I am not sure to understand the purpose of IRQ_handler. Can't you just
> directly call the handler?
We have already have the el1_irq to handle the IRQ.
and we need to save the context before call IRQ_handler.
> 
> >+
> >+    .align 6
> >+el1_sync:
> >+    save_registers 1
> >+    mov     x0, sp
> >+    mrs     x1, esr_el1;
> >+    mrs     x2, far_el1;
> 
> Do you expect the mini-OS to always run with interrupt disabled in EL1? If
> not, you may want to re-enable interrupt here.

okay, I will check it.
> 
> >+    bl      do_sync
> >+    restore_registers 1
> >+
> >+    .align 6
> >+el1_irq:
> >+    save_registers 1
> >+    ldr     x0, IRQ_handler
> >+    blr     x0
> >+    restore_registers 1
> >+
> >+/* Bad Abort numbers */
> >+#define BAD_SYNC    0
> >+#define BAD_IRQ     1
> >+#define BAD_FIQ     2
> >+#define BAD_ERROR   3
> >+
> >+#define el_invalid(name, reason, el)  \
> >+    .align 6;                         \
> >+name##_invalid:                       \
> >+    save_registers  el;               \
> >+    mov     x0, sp;                   \
> >+    mov     x1, #(reason);            \
> >+    mrs     x2, esr_el1;              \
> >+    mrs     x3, far_el1;              \
> >+    b       do_bad_mode;              \
> >+ENDPROC(name##_invalid);              \
> >+
> >+el_invalid(el1_sync, BAD_SYNC, 1);
> >+el_invalid(el0_sync, BAD_SYNC, 0);
> >+el_invalid(el1_irq, BAD_IRQ, 1);
> >+el_invalid(el0_irq, BAD_IRQ, 0);
> >+el_invalid(el1_fiq, BAD_FIQ, 1);
> >+el_invalid(el0_fiq, BAD_FIQ, 0);
> >+el_invalid(el1_error, BAD_ERROR, 1);
> >+el_invalid(el0_error, BAD_ERROR, 0);
> >+
> >+    /* Exception vector entry */
> >+    .macro vector_entry label
> >+    .align  7
> >+    b       \label
> >+    .endm
> >+
> >+    .align  11
> >+ENTRY(vector_table)
> >+    /* Current Exception level with SP_EL0 */
> >+    vector_entry el1_sync_invalid         /* Synchronous EL1t       */
> >+    vector_entry el1_irq_invalid          /* IRQ EL1t               */
> >+    vector_entry el1_fiq_invalid          /* FIQ EL1t               */
> >+    vector_entry el1_error_invalid        /* Error EL1t             */
> >+
> >+    /* Current Exception level with SP_EL1 */
> >+    vector_entry el1_sync                 /* Synchronous EL1h       */
> >+    vector_entry el1_irq                  /* IRQ EL1h               */
> >+    vector_entry el1_fiq_invalid          /* FIQ EL1h               */
> >+    vector_entry el1_error_invalid        /* Error EL1h             */
> >+
> >+    /* Lower Exception level using AArch64 */
> >+    vector_entry el0_sync_invalid         /* Synchronous 64-bit EL0 */
> >+    vector_entry el0_irq_invalid          /* IRQ 64-bit EL0         */
> >+    vector_entry el0_fiq_invalid          /* FIQ 64-bit EL0         */
> >+    vector_entry el0_error_invalid        /* Error 64-bit EL0       */
> >+
> >+    /* Lower Exception level using AArch32 */
> >+    vector_entry el0_sync_invalid         /* Synchronous 32-bit EL0 */
> >+    vector_entry el0_irq_invalid          /* IRQ 32-bit EL0         */
> >+    vector_entry el0_fiq_invalid          /* FIQ 32-bit EL0         */
> >+    vector_entry el0_error_invalid        /* Error 32-bit EL0       */
> 
> It looks like you don't implement EL0. I would try to simplify the EL0
> handling in that case and also add a comment in the code.
okay,
> 
> >+END(vector_table)
> >diff --git a/arch/arm/arm64/traps.c b/arch/arm/arm64/traps.c
> >new file mode 100644
> >index 0000000..62dd2e6
> >--- /dev/null
> >+++ b/arch/arm/arm64/traps.c
> >@@ -0,0 +1,16 @@
> >+#include <mini-os/os.h>
> >+#include <mini-os/arm64/traps.h>
> >+#include <console.h>
> >+
> >+void do_bad_mode(struct pt_regs *regs, int reason,
> >+                  unsigned long esr, unsigned long far)
> >+{
> >+    /* TO DO */
> >+    do_exit();
> >+}
> >+
> >+void do_sync(struct pt_regs *regs, unsigned long esr, unsigned long far)
> >+{
> >+    /* TO DO */
> >+    do_exit();
> >+}
> >diff --git a/include/arm/arm64/traps.h b/include/arm/arm64/traps.h
> >new file mode 100644
> >index 0000000..962f4a6
> >--- /dev/null
> >+++ b/include/arm/arm64/traps.h
> >@@ -0,0 +1,27 @@
> >+#ifndef _TRAPS_H_
> >+#define _TRAPS_H_
> >+
> >+#ifndef __ASSEMBLY__
> >+struct pt_regs {
> >+    uint64_t sp;
> >+    uint64_t pc;
> >+    uint64_t lr;  /* elr */
> >+    uint32_t pstate;
> >+    uint32_t esr;
> >+
> >+    /* From x0 ~ x29 */
> >+    uint64_t x[30];
> >+};
> >+
> >+#else
> >+
> >+#define PT_REG_SIZE   (272)
> >+
> >+#define PT_REG_SP     (0)
> >+#define PT_REG_ELR    (16)
> >+#define PT_REG_SPSR   (24)
> >+#define PT_REG_X      (32)
> 
> I honestly don't like hardcoding offset of the structure. This is a real
> call to mess up in the future (or even now). The lack of comments don't help
> either.
> 
> But I am pretty sure I asked it before. Can't they be generated
> automatically?
I do not know how to generated it automatically :(

thanks
Huang Shijie

_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.