Message ID | 20240215151804.2426-2-Jonathan.Cameron@huawei.com |
---|---|
State | New, archived |
Headers | show |
Series | target/arm: Fix FEAT_HADFS when page tables are in MMIO (cxl) | expand |
On Thu, 15 Feb 2024 at 15:18, Jonathan Cameron <Jonathan.Cameron@huawei.com> wrote: > > I'm far from confident this handling here is correct. Hence > RFC. In particular not sure on what locks I should hold for this > to be even moderately safe. > The function already appears to be inconsistent in what it returns > as the CONFIG_ATOMIC64 block returns the endian converted 'eventual' > value of the cmpxchg whereas the TCG_OVERSIZED_GUEST case returns > the previous value. > > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> > --- > target/arm/ptw.c | 34 ++++++++++++++++++++++++++++++++-- > 1 file changed, 32 insertions(+), 2 deletions(-) > > diff --git a/target/arm/ptw.c b/target/arm/ptw.c > index 5eb3577bcd..37ddb4a4db 100644 > --- a/target/arm/ptw.c > +++ b/target/arm/ptw.c > @@ -711,8 +711,38 @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val, > void *host = ptw->out_host; > > if (unlikely(!host)) { > - fi->type = ARMFault_UnsuppAtomicUpdate; > - return 0; > + /* Can I do a load and store via the physical address */ > + > + bool locked = bql_locked(); > + if (!locked) { > + bql_lock(); > + } > + /* Page table in MMIO Memory Region */ > + if (ptw->out_be) { > + old_val = cpu_to_be64(old_val); > + new_val = cpu_to_be64(new_val); > + cpu_physical_memory_read(ptw->out_phys, &cur_val, 8); This is definitely wrong because it takes no account of address spaces. You need to also account for ptw->out_space. Compare what arm_ldq_ptw() does. > + if (cur_val == old_val) { > + cpu_physical_memory_write(ptw->out_phys, &new_val, 8); > + cur_val = be64_to_cpu(new_val); > + } else { > + cur_val = be64_to_cpu(cur_val); > + } > + } else { > + old_val = cpu_to_le64(old_val); > + new_val = cpu_to_le64(new_val); > + cpu_physical_memory_read(ptw->out_phys, &cur_val, 8); > + if (cur_val == old_val) { > + cpu_physical_memory_write(ptw->out_phys, &new_val, 8); > + cur_val = le64_to_cpu(new_val); > + } else { > + cur_val = le64_to_cpu(cur_val); > + } > + } > + if (!locked) { > + bql_unlock(); > + } > + return cur_val; > } thanks -- PMM
diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 5eb3577bcd..37ddb4a4db 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -711,8 +711,38 @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val, void *host = ptw->out_host; if (unlikely(!host)) { - fi->type = ARMFault_UnsuppAtomicUpdate; - return 0; + /* Can I do a load and store via the physical address */ + + bool locked = bql_locked(); + if (!locked) { + bql_lock(); + } + /* Page table in MMIO Memory Region */ + if (ptw->out_be) { + old_val = cpu_to_be64(old_val); + new_val = cpu_to_be64(new_val); + cpu_physical_memory_read(ptw->out_phys, &cur_val, 8); + if (cur_val == old_val) { + cpu_physical_memory_write(ptw->out_phys, &new_val, 8); + cur_val = be64_to_cpu(new_val); + } else { + cur_val = be64_to_cpu(cur_val); + } + } else { + old_val = cpu_to_le64(old_val); + new_val = cpu_to_le64(new_val); + cpu_physical_memory_read(ptw->out_phys, &cur_val, 8); + if (cur_val == old_val) { + cpu_physical_memory_write(ptw->out_phys, &new_val, 8); + cur_val = le64_to_cpu(new_val); + } else { + cur_val = le64_to_cpu(cur_val); + } + } + if (!locked) { + bql_unlock(); + } + return cur_val; } /*
I'm far from confident this handling here is correct. Hence RFC. In particular not sure on what locks I should hold for this to be even moderately safe. The function already appears to be inconsistent in what it returns as the CONFIG_ATOMIC64 block returns the endian converted 'eventual' value of the cmpxchg whereas the TCG_OVERSIZED_GUEST case returns the previous value. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> --- target/arm/ptw.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-)