[PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller
Cédric Le Goater
clg at kaod.org
Mon Nov 28 23:34:15 AEDT 2016
On 11/28/2016 02:55 AM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
>> The lock register is unlocked with a write of a special value and
>> locked with a write of any other value. When unlocked, reads return
>> one and when locked a zero.
>>
>>> Signed-off-by: Cédric Le Goater <clg at kaod.org>
>> ---
>> hw/misc/aspeed_sdmc.c | 28 +++++++++++++++++++---------
>> include/hw/misc/aspeed_sdmc.h | 1 +
>> 2 files changed, 20 insertions(+), 9 deletions(-)
>>
>> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
>> index 5f3ac0b6f608..867caa2d64dc 100644
>> --- a/hw/misc/aspeed_sdmc.c
>> +++ b/hw/misc/aspeed_sdmc.c
>> @@ -83,17 +83,22 @@
>> static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
>> {
>> AspeedSDMCState *s = ASPEED_SDMC(opaque);
>> + uint64_t val = 0;
>>
>> addr >>= 2;
>>
>> - if (addr >= ARRAY_SIZE(s->regs)) {
>> + switch (addr) {
>> + case R_PROT:
>> + val = s->unlocked;
>> + break;
>> + default:
>> qemu_log_mask(LOG_GUEST_ERROR,
>> "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
>> __func__, addr);
>> - return 0;
>> + break;
>> }
>>
>> - return s->regs[addr];
>> + return val;
>
> This suggests we only care about R_PROT - the change returns 0 for the
> value of other registers. That doesn't seem right.
Well, the read already returned 0 and that is what you get most of the
time on real HW. Some time you get a 0xFFFFFFFF.
Thanks,
C.
> Andrew
>
>> }
>>
>> static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>> @@ -103,19 +108,18 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>>
>> addr >>= 2;
>>
>> - if (addr >= ARRAY_SIZE(s->regs)) {
>> - qemu_log_mask(LOG_GUEST_ERROR,
>> - "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
>> - __func__, addr);
>> + if (addr == R_PROT) {
>> + s->unlocked = (data == PROT_KEY_UNLOCK);
>> return;
>> }
>>
>> - if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) {
>> + if (!s->unlocked) { /* TODO protect : MCR04 ∼ MCR7C */
>> qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
>> return;
>> }
>>
>> - if (addr == R_CONF) {
>> + switch (addr) {
>> + case R_CONF:
>> /* Make sure readonly bits are kept */
>> switch (s->silicon_rev) {
>> case AST2400_A0_SILICON_REV:
>> @@ -128,6 +132,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>> default:
>> g_assert_not_reached();
>> }
>> + break;
>> + default:
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
>> + __func__, addr << 2);
>> + return;
>> }
>>
>> s->regs[addr] = data;
>> diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
>> index 551c8afdf4be..a4415d9efc2f 100644
>> --- a/include/hw/misc/aspeed_sdmc.h
>> +++ b/include/hw/misc/aspeed_sdmc.h
>> @@ -28,6 +28,7 @@ typedef struct AspeedSDMCState {
>> uint32_t ram_bits;
>> uint64_t ram_size;
>>
>> + bool unlocked;
>> } AspeedSDMCState;
>>
>> #endif /* ASPEED_SDMC_H */
More information about the openbmc
mailing list