[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH v2 08/30] target/loongarch: Add LoongArch CSR/IOCSR instr
From: |
yangxiaojuan |
Subject: |
Re: [RFC PATCH v2 08/30] target/loongarch: Add LoongArch CSR/IOCSR instruction |
Date: |
Wed, 17 Nov 2021 16:48:03 +0800 |
User-agent: |
Mozilla/5.0 (X11; Linux mips64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 |
Hi, Richard:
On 11/12/2021 01:43 AM, Richard Henderson wrote:
> On 11/11/21 2:35 AM, Xiaojuan Yang wrote:
>> This includes:
>> - CSRRD
>> - CSRWR
>> - CSRXCHG
>> - IOCSR{RD/WR}.{B/H/W/D}
>
> I think IOCSR should be in a separate patch.
> It's completely unrelated to the other CSRs.
>
>> +target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t csr)
>> +{
>> + int64_t v;
>> +
>> + switch (csr) {
>> + case LOONGARCH_CSR_PGD:
>> + if (env->CSR_TLBRERA & 0x1) {
>> + v = env->CSR_TLBRBADV;
>> + } else {
>> + v = env->CSR_BADV;
>> + }
>> +
>> + if ((v >> 63) & 0x1) {
>> + v = env->CSR_PGDH;
>> + } else {
>> + v = env->CSR_PGDL;
>> + }
>> + v = v & TARGET_PHYS_MASK;
>
> This csr is defined to be GRLEN bits; I this mask looks wrong.
>
>> + default:
>> + assert(0);
>
> g_assert_not_reached.
>
>> + switch (csr) {
>> + case LOONGARCH_CSR_ASID:
>> + old_v = env->CSR_ASID;
>> + env->CSR_ASID = val;
>
> Mask the write to the field; you don't want to corrupt ASIDBITS, or the other
> read-only bits.
Ok, all above have been modified.
>
>> + case LOONGARCH_CSR_TCFG:
>> + old_v = env->CSR_TCFG;
>> + cpu_loongarch_store_stable_timer_config(env, val);
>> + break;
>> + case LOONGARCH_CSR_TINTCLR:
>> + old_v = 0;
>> + qemu_irq_lower(env->irq[IRQ_TIMER]);
>
> The interrupt is not documented to clear on any write; only writes of 1 to
> bit 0.
I think the manual has mentioned at 7.6.5 which says when 1 is written to this
bit, the clock interrupt
flag is cleared.
>
>> + default:
>> + assert(0);
>
> g_assert_not_reached.
>
>> + }
>> +
>> + return old_v;
>> +}
>> +
>> +target_ulong helper_csr_xchgq(CPULoongArchState *env, target_ulong val,
>> + target_ulong mask, uint64_t csr)
>> +{
>> + target_ulong tmp;
>> + target_ulong v = val & mask;
>
> I think it would be less confusing to name the input parameter new_val, and
> the local temporary old_val.
>
>> +#define CASE_CSR_XCHGQ(csr) \
>> + case LOONGARCH_CSR_ ## csr: \
>> + { \
>> + val = env->CSR_ ## csr; \
>> + env->CSR_ ## csr = (env->CSR_ ## csr) & (~mask); \
>> + env->CSR_ ## csr = (env->CSR_ ## csr) | v; \
>
> old_val = env->CSR_##csr;
> env->CSR_##csr = (old_val & ~mask) | (new_val & mask);
>
>
>> + switch (csr) {
>> + CASE_CSR_XCHGQ(CRMD)
>
> I wonder if all of this would be better with a table of offsets, which could
> be shared with the translator.
>
> #define CSR_OFF(X) [LOONGARCH_CSR_##X] = offsetof(CPUArchState, CSR_##X)
>
> static const int csr_offsets[] = {
> CSR_OFF(CRMD),
> ...
> };
>
> int cpu_csr_offset(unsigned csr_num)
> {
> if (csr_num < ARRAY_SIZE(csr_offsets)) {
> return csr_offsets[csr_num];
> }
> return 0;
> }
>
> Which reduces this function to
>
> unsigned csr_offset = cpu_csr_offset(csr_num);
> if (csr_offset == 0) {
> /* CSR is undefined: read as 0, write ignored. */
> return 0;
> }
>
> uint64_t *csr = (void *)env + csr_offset;
> uint64_t old_val = *csr;
>
> new_val = (new_val & mask) | (old_val & ~mask);
>
> *csr = (old_val & ~mask) | (new_val & mask);
>
> if (csr_num == LOONGARCH_CSR_TCFG) {
> cpu_loongarch_store_stable_timer_config(env, new_val);
> } else {
> *csr = new_val;
> }
> return old_val;
>
>> +uint64_t helper_iocsr_read(CPULoongArchState *env, target_ulong r_addr,
>> + uint32_t size)
>> +{
>> + LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
>> + int cpuid = env_cpu(env)->cpu_index;
>> +
>> + if (((r_addr & 0xff00) == 0x1000) || ((r_addr & 0xff00) == 0x1800)) {
>> + r_addr = r_addr + ((target_ulong)(cpuid & 0x3) << 8);
>> + }
>
> This looks to be something that should be controlled by the address space
> assigned to each cpu.
>
> But it's hard to tell.
>
> Where is the documentation for this? I didn't immediately find it in 3A5000
> Technical Reference Manual, Chapter 10.
Yes, most iocsr instructions introduced on 3A5000 Technical Reference Manual,
Chapter 10.
Table 10-2, 10-3, 10-4, 10-5 and 11-10 lists per core iocsr
>
>> +void helper_iocsr_write(CPULoongArchState *env, target_ulong w_addr,
>> + target_ulong val, uint32_t size)
>> +{
>> + LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
>> + int cpuid = env_cpu(env)->cpu_index;
>> + int mask, i;
>> +
>> + /*
>> + * For IPI send, Mail send, ANY send adjust addr and val
>> + * according to their real meaning
>> + */
>> + if (w_addr == 0x1040) { /* IPI send */
>> + cpuid = (val >> 16) & 0x3ff;
>> + val = 1UL << (val & 0x1f);
>> + w_addr = 0x1008;
>
> I don't see any interrupts actually being raised?
I define the memory region ops at the IPI interrupt controller, the ipi write
here will lead to the ops and raise the
interrupt at the read/write function. I don't know if this is appropriate, but
most of the iocsr read/write are closely
related to interrupt controller.
>
>> +static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a)
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
>> +
>> + gen_helper_check_plv(cpu_env);
>
> You don't need an external call. PLV should be part of TB_FLAGS, so you can
> check this during translation.
>
>> + case LOONGARCH_CSR_TVAL:
>> + gen_helper_csr_rdq(dest, cpu_env, tcg_constant_i64(a->csr));
>> + break;
>> + default:
>> + assert(0);
>
> The assert was definitely wrong, as it allows incorrect programs to crash
> qemu. In addition, unknown csr read as 0.
>
>> + CASE_CSR_WRQ(MISC)
>
> You don't actually support any of the MISC bits yet.
> You should make this register read-only until you do.
>
> How many more registers are read-only, or have read-only fields that you are
> not checking?
>
Yes, I will check all of them.
Futher, Can you help review the remaining patches? since the board and machine
code needs rewrite. A new version
is need. The remaining patches are:
0011-target-loongarch-Add-LoongArch-interrupt-and-excepti.patch
0012-target-loongarch-Add-timer-related-instructions-supp.patch
0013-target-loongarch-Add-gdb-support.patch
0014-target-loongarch-Implement-privilege-instructions-di.patch
Thank you for all your work.
Xiaojuan
>
> r~
- [RFC PATCH v2 01/30] target/loongarch: Update README, (continued)
- [RFC PATCH v2 01/30] target/loongarch: Update README, Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 10/30] target/loongarch: Add other core instructions support, Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 11/30] target/loongarch: Add LoongArch interrupt and exception handle, Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 15/30] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform, Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 08/30] target/loongarch: Add LoongArch CSR/IOCSR instruction, Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 12/30] target/loongarch: Add timer related instructions support., Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 18/30] hw/loongarch: Add LoongArch ipi interrupt support(IPI), Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 20/30] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI), Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 14/30] target/loongarch: Implement privilege instructions disassembly, Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 17/30] hw/loongarch: Add LoongArch cpu interrupt support(CPUINTC), Xiaojuan Yang, 2021/11/10
- [RFC PATCH v2 19/30] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC), Xiaojuan Yang, 2021/11/10