//! Reservation isolation at trap entry, frame resume, and user context switches.
.text;
    li %s0 0x40010000;
    slli %s0 %s0 1;
    sd %sp 0(%s0);
    li %t0 4096;
    sub %t0 %sp %t0;
    sd %t0 8(%s0);
    sd %zero 16(%s0);
    la %t0 @handler;
    sd %t0 24(%s0);
    mv %a0 %s0;
    call @kernel::trap::install;
    addi %s1 %s0 80;

// Enter the vector with a live reservation and the machine trap CSR state.
    la %t0 @resumed;
    csrw mepc %t0;
    li %t0 11;
    csrw mcause %t0;
    li %t0 0x1800;
    csrw mstatus %t0;
    lr.d %t0 (%s1);
    j @kernel::trap::vector;
@resumed
    sc.d %t0 %zero (%s1);
    beqz %t0 @fail;
    ld %t0 0(%s1);
    bnez %t0 @fail;
    li %t0 2;
    sd %t0 88(%s0);
    la %t0 @first;
    csrw mepc %t0;
    csrw mstatus %zero;
    mret;

// The first user context retains its loaded value across a peer's execution.
@first
    lr.d %a2 (%s1);
    ecall;
@firstResume
    sc.d %a3 %a2 (%s1);
    beqz %a3 @fail;
    ld %t0 0(%s1);
    li %t1 1;
    bne %t0 %t1 @fail;
    ecall;
    j @fail;

// The peer changes shared memory and reserves the same location before exit.
@peer
    li %t0 1;
    sd %t0 0(%s1);
    lr.d %t0 (%s1);
    ecall;
    j @fail;

// Inject a live return reservation after trap entry has completed.
@handler
    ld %t0 88(%s0);
    beqz %t0 @entryCheck;
    ld %t1 272(%a0);
    li %t2 8;
    bne %t1 %t2 @fail;
    li %t1 2;
    beq %t0 %t1 @switchPeer;
    li %t1 3;
    beq %t0 %t1 @switchFirst;
    li %t1 4;
    bne %t0 %t1 @fail;
    j @success;
@entryCheck
    sc.d %t0 %zero (%s1);
    beqz %t0 @fail;
    li %t0 1;
    sd %t0 88(%s0);
    lr.d %t0 (%s1);
    ret;
@switchPeer
    li %t0 3;
    sd %t0 88(%s0);
    la %t0 @peer;
    sd %t0 256(%a0);
    ret;
@switchFirst
    li %t0 4;
    sd %t0 88(%s0);
    la %t0 @firstResume;
    sd %t0 256(%a0);
    lr.d %t0 (%s1);
    ret;
@success
    li %t0 0x10001000;
    li %t1 0x5555;
    sw %t1 0(%t0);
@fail
    li %t0 0x10001000;
    li %t1 0x13333;
    sw %t1 0(%t0);
    ebreak;
