All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sebastian Macke <sebastian@macke.de>
To: Jia Liu <proljc@gmail.com>
Cc: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>, blue@cmd.nu
Subject: Re: [Qemu-devel] [PATCH 2/2] target-openrisc: Add l.lwa/l.swa support
Date: Mon, 26 Jan 2015 11:18:15 +0100	[thread overview]
Message-ID: <54C61467.3050805@macke.de> (raw)
In-Reply-To: <CAJBMM-uhiOQrRwBK-FiVJK24DUyFWDh0eVbSujswU5C=Y13wqg@mail.gmail.com>

Hi Jia,

On 1/26/2015 10:50 AM, Jia Liu wrote:
> Hi Sebastian, Christian
>
> On Sun, Jan 25, 2015 at 6:25 PM, Sebastian Macke <sebastian@macke.de> wrote:
>> From: Christian Svensson <blue@cmd.nu>
>>
>> This patch adds support for atomic locks
>> and is an adaption from https://github.com/bluecmd/or1k-qemu/commits/or32-optimize
>>
>> Tested via the atomic lock implementation of musl
>>
>> Signed-off-by: Christian Svensson <blue@cmd.nu>
>> Signed-off-by: Sebastian Macke <sebastian@macke.de>
>> ---
>>   target-openrisc/cpu.h       |  3 ++
>>   target-openrisc/interrupt.c |  3 ++
>>   target-openrisc/translate.c | 77 ++++++++++++++++++++++++++++++++++++++++++---
>>   3 files changed, 79 insertions(+), 4 deletions(-)
>>
>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
>> index 69b96c6..abdba75 100644
>> --- a/target-openrisc/cpu.h
>> +++ b/target-openrisc/cpu.h
>> @@ -302,6 +302,9 @@ typedef struct CPUOpenRISCState {
>>                                    in solt so far.  */
>>       uint32_t btaken;          /* the SR_F bit */
>>
>> +    target_ulong lock_addr;   /* Atomicity lock address. */
>> +    target_ulong lock_value;  /* Atomicity lock value. */
>> +
>>       CPU_COMMON
>>
>>       /* Fields from here on are preserved across CPU reset. */
>> diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
>> index e480cfd..68d554c 100644
>> --- a/target-openrisc/interrupt.c
>> +++ b/target-openrisc/interrupt.c
>> @@ -54,6 +54,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>>       env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
>>       env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
>>
>> +    /* invalidate lock */
>> +    env->cpu_lock_addr = -1;
>> +
>>       if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
>>           env->pc = (cs->exception_index << 8);
>>       } else {
>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>> index 543aa67..6401b4b 100644
>> --- a/target-openrisc/translate.c
>> +++ b/target-openrisc/translate.c
>> @@ -55,6 +55,8 @@ typedef struct DisasContext {
>>   static TCGv_ptr cpu_env;
>>   static TCGv cpu_sr;
>>   static TCGv cpu_R[32];
>> +static TCGv cpu_lock_addr;
>> +static TCGv cpu_lock_value;
>>   static TCGv cpu_pc;
>>   static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
>>   static TCGv cpu_npc;
>> @@ -82,6 +84,12 @@ void openrisc_translate_init(void)
>>       env_flags = tcg_global_mem_new_i32(TCG_AREG0,
>>                                          offsetof(CPUOpenRISCState, flags),
>>                                          "flags");
>> +    cpu_lock_addr = tcg_global_mem_new(TCG_AREG0,
>> +                                       offsetof(CPUOpenRISCState, lock_addr),
>> +                                       "lock_addr");
>> +    cpu_lock_value = tcg_global_mem_new(TCG_AREG0,
>> +                                        offsetof(CPUOpenRISCState, lock_value),
>> +                                        "lock_value");
>>       cpu_pc = tcg_global_mem_new(TCG_AREG0,
>>                                   offsetof(CPUOpenRISCState, pc), "pc");
>>       cpu_npc = tcg_global_mem_new(TCG_AREG0,
>> @@ -254,17 +262,67 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
>>       gen_sync_flags(dc);
>>   }
>>
>> +/* According to the OpenRISC specification we should poison our atomic lock
>> + * if any other store is detected to the same address. For the sake of speed
>> + * and because we're single-threaded we guarantee that atomic stores
>> + * fail only if an atomic load or another atomic store
>> + * is executed.
>> + *
>> + * To prevent the potential case of an ordinary store, we save
>> + * the *value* of the address at the lock time. */
>> +
>> +static void gen_atomic_load(TCGv tD, TCGv t0, DisasContext *dc)
>> +{
>> +    tcg_gen_qemu_ld_tl(tD, t0, dc->mem_idx, MO_TEUL);
>> +    tcg_gen_mov_i32(cpu_lock_addr, t0);
>> +    tcg_gen_mov_i32(cpu_lock_value, tD);
>> +}
>> +
>> +static void gen_atomic_store(TCGv tB, TCGv t0, DisasContext *dc)
>> +{
>> +    int store_fail;
>> +    int store_done;
>> +
>> +    store_fail = gen_new_label();
>> +    store_done = gen_new_label();
>> +
>> +    /* check address */
>> +    tcg_gen_brcond_i32(TCG_COND_NE, t0, cpu_lock_addr, store_fail);
>> +
>> +    /* check value */
>> +    TCGv val = tcg_temp_new();
>> +    tcg_gen_qemu_ld_tl(val, t0, dc->mem_idx, MO_TEUL);
>> +    tcg_gen_brcond_i32(TCG_COND_NE, val, cpu_lock_value, store_fail);
>> +    tcg_temp_free(val);
>> +
>> +    /* success of atomic access */
>> +    tcg_gen_qemu_st_tl(tB, t0, dc->mem_idx, MO_TEUL);
>> +    tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F);
>> +    tcg_gen_br(store_done);
>> +
>> +    gen_set_label(store_fail);
>> +    tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F);
>> +
>> +    gen_set_label(store_done);
>> +    /* the atomic store invalidates the lock address. */
>> +    tcg_gen_movi_i32(cpu_lock_addr, -1);
>> +}
>> +
>>   static void gen_loadstore(DisasContext *dc, uint32 op0,
>>                             uint32_t ra, uint32_t rb, uint32_t rd,
>>                             uint32_t offset)
>>   {
>>       TCGv t0 = cpu_R[ra];
>>       if (offset != 0) {
>> -        t0 = tcg_temp_new();
>> +        t0 = tcg_temp_local_new();
>>           tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(offset, 16));
>>       }
>>
>>       switch (op0) {
>> +    case 0x1b:    /* l.lwa */
>> +        gen_atomic_load(cpu_R[rd], t0, dc);
>> +        break;
>> +
>>       case 0x21:    /* l.lwz */
>>           tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, MO_TEUL);
>>           break;
>> @@ -289,6 +347,10 @@ static void gen_loadstore(DisasContext *dc, uint32 op0,
>>           tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, MO_TESW);
>>           break;
>>
>> +    case 0x33:    /* l.swa */
>> +        gen_atomic_store(cpu_R[rb], t0, dc);
>> +        break;
>> +
>>       case 0x35:    /* l.sw */
>>           tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, MO_TEUL);
>>           break;
>> @@ -759,9 +821,6 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
>>       }
>>   }
>>
>> -
>> -
>> -
> It should be blank lines in here in [patch 1/2].

Yes, looks like I added three lines in patch 1/2 and then removed them 
in patch 2/2.
I guess if both patches are accepted it does not matter. Otherwise I 
will fix these in revision 2.

>
>>   static void dec_misc(DisasContext *dc, uint32_t insn)
>>   {
>>       uint32_t op0, op1;
>> @@ -905,6 +964,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>>           gen_loadstore(dc, op0, ra, rb, rd, I16);
>>   #endif*/
>>
>> +    case 0x1b:    /* l.lwa */
>> +        LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
>> +        gen_loadstore(dc, op0, ra, rb, rd, I16);
>> +        break;
>> +
> Is it a new instruction new added into OpenRISC?

Yes, they were added last year.
http://opencores.org/websvn,filedetails?repname=openrisc&path=%2Fopenrisc%2Ftrunk%2Fdocs%2Fopenrisc-arch-1.1-rev0.pdf
Previously the kernel handled those atomic calls for single core 
implementations.
But we also managed to run multi-core OpenRISC machine. And here the 
instructions are absolutely necessary.

Fact is, that almost none of our toolchains work anymore without these 
new instructions.

>>       case 0x21:    /* l.lwz */
>>           LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
>>           gen_loadstore(dc, op0, ra, rb, rd, I16);
>> @@ -1072,6 +1136,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>>           gen_loadstore(dc, op0, ra, rb, rd, tmp);
>>   #endif*/
>>
>> +    case 0x33:    /* l.swa */
>> +        LOG_DIS("l.swa %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>> +        gen_loadstore(dc, op0, ra, rb, rd, tmp);
>> +        break;
>> +
>>       case 0x35:    /* l.sw */
>>           LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>           gen_loadstore(dc, op0, ra, rb, rd, tmp);
>> --
>> 2.2.2
>>
> Regards,
> Jia

  parent reply	other threads:[~2015-01-26 10:18 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-25 10:25 [Qemu-devel] [PATCH 0/2] target-openrisc: Add atomic instructions Sebastian Macke
2015-01-25 10:25 ` [Qemu-devel] [PATCH 1/2] target-openrisc: Separate of load/store instructions Sebastian Macke
2015-01-26  9:47   ` Jia Liu
2015-01-25 10:25 ` [Qemu-devel] [PATCH 2/2] target-openrisc: Add l.lwa/l.swa support Sebastian Macke
2015-01-26  9:50   ` Jia Liu
2015-01-26 10:15     ` Christian Svensson
2015-01-26 10:18     ` Sebastian Macke [this message]
2015-01-28  2:28       ` Jia Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54C61467.3050805@macke.de \
    --to=sebastian@macke.de \
    --cc=blue@cmd.nu \
    --cc=proljc@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.