* [PATCH v3 1/9] riscv/boot: Add a missing header include
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-20 6:01 ` Philippe Mathieu-Daudé
2020-05-19 21:31 ` [PATCH v3 2/9] target/riscv: Don't overwrite the reset vector Alistair Francis
` (7 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
Currently every c file that includes boot.h also includes loader.h
before it. Which is why the build works fine. We should be able to
include just boot.h though so this is a small fixup to allow that.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
---
include/hw/riscv/boot.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 474a940ad5..9daa98da08 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -21,6 +21,7 @@
#define RISCV_BOOT_H
#include "exec/cpu-defs.h"
+#include "hw/loader.h"
void riscv_find_and_load_firmware(MachineState *machine,
const char *default_machine_firmware,
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3 1/9] riscv/boot: Add a missing header include
2020-05-19 21:31 ` [PATCH v3 1/9] riscv/boot: Add a missing header include Alistair Francis
@ 2020-05-20 6:01 ` Philippe Mathieu-Daudé
2020-05-20 16:09 ` Alistair Francis
0 siblings, 1 reply; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-05-20 6:01 UTC (permalink / raw)
To: Alistair Francis, qemu-devel, qemu-riscv; +Cc: alistair23, bmeng.cn, palmer
On 5/19/20 11:31 PM, Alistair Francis wrote:
> Currently every c file that includes boot.h also includes loader.h
> before it. Which is why the build works fine. We should be able to
> include just boot.h though so this is a small fixup to allow that.
What about:
'As the functions declared in this header use the symbol_fn_t
typedef itself declared in "hw/loader.h", we need to include
it here to make the header file self-contained.'
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Reviewed-by: Bin Meng <bin.meng@windriver.com>
> ---
> include/hw/riscv/boot.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> index 474a940ad5..9daa98da08 100644
> --- a/include/hw/riscv/boot.h
> +++ b/include/hw/riscv/boot.h
> @@ -21,6 +21,7 @@
> #define RISCV_BOOT_H
>
> #include "exec/cpu-defs.h"
> +#include "hw/loader.h"
>
> void riscv_find_and_load_firmware(MachineState *machine,
> const char *default_machine_firmware,
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v3 1/9] riscv/boot: Add a missing header include
2020-05-20 6:01 ` Philippe Mathieu-Daudé
@ 2020-05-20 16:09 ` Alistair Francis
0 siblings, 0 replies; 21+ messages in thread
From: Alistair Francis @ 2020-05-20 16:09 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: open list:RISC-V, Palmer Dabbelt, Alistair Francis,
qemu-devel@nongnu.org Developers, Bin Meng
On Tue, May 19, 2020 at 11:01 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> On 5/19/20 11:31 PM, Alistair Francis wrote:
> > Currently every c file that includes boot.h also includes loader.h
> > before it. Which is why the build works fine. We should be able to
> > include just boot.h though so this is a small fixup to allow that.
>
> What about:
>
> 'As the functions declared in this header use the symbol_fn_t
> typedef itself declared in "hw/loader.h", we need to include
> it here to make the header file self-contained.'
Sounds good.
Alistair
>
> >
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> > Reviewed-by: Bin Meng <bin.meng@windriver.com>
> > ---
> > include/hw/riscv/boot.h | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> > index 474a940ad5..9daa98da08 100644
> > --- a/include/hw/riscv/boot.h
> > +++ b/include/hw/riscv/boot.h
> > @@ -21,6 +21,7 @@
> > #define RISCV_BOOT_H
> >
> > #include "exec/cpu-defs.h"
> > +#include "hw/loader.h"
> >
> > void riscv_find_and_load_firmware(MachineState *machine,
> > const char *default_machine_firmware,
> >
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v3 2/9] target/riscv: Don't overwrite the reset vector
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
2020-05-19 21:31 ` [PATCH v3 1/9] riscv/boot: Add a missing header include Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-21 1:45 ` Bin Meng
2020-05-19 21:31 ` [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU Alistair Francis
` (6 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
The reset vector is set in the init function don't set it again in
realize.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
target/riscv/cpu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 059d71f2c7..5eb3c02735 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -133,6 +133,7 @@ static void riscv_base32_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
set_misa(env, 0);
+ set_resetvec(env, DEFAULT_RSTVEC);
}
static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
@@ -180,6 +181,7 @@ static void riscv_base64_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
set_misa(env, 0);
+ set_resetvec(env, DEFAULT_RSTVEC);
}
static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
@@ -399,7 +401,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
}
set_priv_version(env, priv_version);
- set_resetvec(env, DEFAULT_RSTVEC);
if (cpu->cfg.mmu) {
set_feature(env, RISCV_FEATURE_MMU);
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3 2/9] target/riscv: Don't overwrite the reset vector
2020-05-19 21:31 ` [PATCH v3 2/9] target/riscv: Don't overwrite the reset vector Alistair Francis
@ 2020-05-21 1:45 ` Bin Meng
0 siblings, 0 replies; 21+ messages in thread
From: Bin Meng @ 2020-05-21 1:45 UTC (permalink / raw)
To: Alistair Francis
Cc: Palmer Dabbelt, Philippe Mathieu-Daudé,
open list:RISC-V, qemu-devel@nongnu.org Developers,
Alistair Francis
On Wed, May 20, 2020 at 5:39 AM Alistair Francis
<alistair.francis@wdc.com> wrote:
>
> The reset vector is set in the init function don't set it again in
> realize.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
> target/riscv/cpu.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
2020-05-19 21:31 ` [PATCH v3 1/9] riscv/boot: Add a missing header include Alistair Francis
2020-05-19 21:31 ` [PATCH v3 2/9] target/riscv: Don't overwrite the reset vector Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-22 7:50 ` LIU Zhiwei
2020-05-19 21:31 ` [PATCH v3 4/9] riscv: Initial commit of OpenTitan machine Alistair Francis
` (5 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
Ibex is a small and efficient, 32-bit, in-order RISC-V core with
a 2-stage pipeline that implements the RV32IMC instruction set
architecture.
For more details on lowRISC see here:
https://github.com/lowRISC/ibex
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
---
target/riscv/cpu.h | 1 +
target/riscv/cpu.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d0e7f5b9c5..8733d7467f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -35,6 +35,7 @@
#define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
#define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
#define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
#define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5eb3c02735..eb2bbc87ae 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -156,6 +156,15 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
set_feature(env, RISCV_FEATURE_PMP);
}
+static void rv32imcu_nommu_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVC | RVU);
+ set_priv_version(env, PRIV_VERSION_1_10_0);
+ set_resetvec(env, 0x8090);
+ set_feature(env, RISCV_FEATURE_PMP);
+}
+
static void rv32imacu_nommu_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
@@ -619,6 +628,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
#if defined(TARGET_RISCV32)
DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32imcu_nommu_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init),
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU
2020-05-19 21:31 ` [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU Alistair Francis
@ 2020-05-22 7:50 ` LIU Zhiwei
2020-05-26 17:12 ` Alistair Francis
0 siblings, 1 reply; 21+ messages in thread
From: LIU Zhiwei @ 2020-05-22 7:50 UTC (permalink / raw)
To: Alistair Francis; +Cc: philmd, Palmer Dabbelt, bmeng.cn, qemu-riscv, qemu-devel
On 2020/5/20 5:31, Alistair Francis wrote:
> Ibex is a small and efficient, 32-bit, in-order RISC-V core with
> a 2-stage pipeline that implements the RV32IMC instruction set
> architecture.
>
> For more details on lowRISC see here:
> https://github.com/lowRISC/ibex
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Bin Meng <bin.meng@windriver.com>
> ---
> target/riscv/cpu.h | 1 +
> target/riscv/cpu.c | 10 ++++++++++
> 2 files changed, 11 insertions(+)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index d0e7f5b9c5..8733d7467f 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -35,6 +35,7 @@
> #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
> #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
> #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
> +#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
> #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
> #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
> #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 5eb3c02735..eb2bbc87ae 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -156,6 +156,15 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
> set_feature(env, RISCV_FEATURE_PMP);
> }
>
> +static void rv32imcu_nommu_cpu_init(Object *obj)
> +{
> + CPURISCVState *env = &RISCV_CPU(obj)->env;
> + set_misa(env, RV32 | RVI | RVM | RVC | RVU);
> + set_priv_version(env, PRIV_VERSION_1_10_0);
> + set_resetvec(env, 0x8090);
Hi Alistair,
I see all RISC-V cpus have an reset vector which acts as the first pc
when machine boots up.
However, the first pc is more like an attribute of a machine, not a cpu.
Another reason is that the cpu names are a combination of ISA.
Then the cpus from different vendors may have same ISA, with different
reset vectors.
Do you think so?
Zhiwei
> + set_feature(env, RISCV_FEATURE_PMP);
> +}
> +
> static void rv32imacu_nommu_cpu_init(Object *obj)
> {
> CPURISCVState *env = &RISCV_CPU(obj)->env;
> @@ -619,6 +628,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
> DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
> #if defined(TARGET_RISCV32)
> DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init),
> + DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32imcu_nommu_cpu_init),
> DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
> DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init),
> DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init),
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU
2020-05-22 7:50 ` LIU Zhiwei
@ 2020-05-26 17:12 ` Alistair Francis
2020-05-27 1:58 ` LIU Zhiwei
0 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-26 17:12 UTC (permalink / raw)
To: LIU Zhiwei
Cc: open list:RISC-V, qemu-devel@nongnu.org Developers,
Alistair Francis, Palmer Dabbelt, Bin Meng,
Philippe Mathieu-Daudé
On Fri, May 22, 2020 at 12:51 AM LIU Zhiwei <zhiwei_liu@c-sky.com> wrote:
>
>
>
> On 2020/5/20 5:31, Alistair Francis wrote:
> > Ibex is a small and efficient, 32-bit, in-order RISC-V core with
> > a 2-stage pipeline that implements the RV32IMC instruction set
> > architecture.
> >
> > For more details on lowRISC see here:
> > https://github.com/lowRISC/ibex
> >
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > Reviewed-by: Bin Meng <bin.meng@windriver.com>
> > ---
> > target/riscv/cpu.h | 1 +
> > target/riscv/cpu.c | 10 ++++++++++
> > 2 files changed, 11 insertions(+)
> >
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index d0e7f5b9c5..8733d7467f 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -35,6 +35,7 @@
> > #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
> > #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
> > #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
> > +#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
> > #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
> > #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
> > #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 5eb3c02735..eb2bbc87ae 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -156,6 +156,15 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
> > set_feature(env, RISCV_FEATURE_PMP);
> > }
> >
> > +static void rv32imcu_nommu_cpu_init(Object *obj)
> > +{
> > + CPURISCVState *env = &RISCV_CPU(obj)->env;
> > + set_misa(env, RV32 | RVI | RVM | RVC | RVU);
> > + set_priv_version(env, PRIV_VERSION_1_10_0);
> > + set_resetvec(env, 0x8090);
> Hi Alistair,
>
> I see all RISC-V cpus have an reset vector which acts as the first pc
> when machine boots up.
> However, the first pc is more like an attribute of a machine, not a cpu.
In general it seems to be a CPU property. I assume that some CPUs
would allow the reset vector to be selectable though, in which case it
becomes a board property.
>
> Another reason is that the cpu names are a combination of ISA.
> Then the cpus from different vendors may have same ISA, with different
> reset vectors.
>
> Do you think so?
If you are worried about CPUs with different vectors we could always
make it a property in the future and have boards override it. I don't
think we need that yet (only 1 CPU is different) but it is an easy
future change.
Alistair
>
> Zhiwei
> > + set_feature(env, RISCV_FEATURE_PMP);
> > +}
> > +
> > static void rv32imacu_nommu_cpu_init(Object *obj)
> > {
> > CPURISCVState *env = &RISCV_CPU(obj)->env;
> > @@ -619,6 +628,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
> > DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
> > #if defined(TARGET_RISCV32)
> > DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init),
> > + DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32imcu_nommu_cpu_init),
> > DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
> > DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init),
> > DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init),
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU
2020-05-26 17:12 ` Alistair Francis
@ 2020-05-27 1:58 ` LIU Zhiwei
2020-05-27 16:44 ` Alistair Francis
0 siblings, 1 reply; 21+ messages in thread
From: LIU Zhiwei @ 2020-05-27 1:58 UTC (permalink / raw)
To: Alistair Francis
Cc: open list:RISC-V, qemu-devel@nongnu.org Developers,
Alistair Francis, Palmer Dabbelt, Bin Meng,
Philippe Mathieu-Daudé
On 2020/5/27 1:12, Alistair Francis wrote:
> On Fri, May 22, 2020 at 12:51 AM LIU Zhiwei <zhiwei_liu@c-sky.com> wrote:
>>
>>
>> On 2020/5/20 5:31, Alistair Francis wrote:
>>> Ibex is a small and efficient, 32-bit, in-order RISC-V core with
>>> a 2-stage pipeline that implements the RV32IMC instruction set
>>> architecture.
>>>
>>> For more details on lowRISC see here:
>>> https://github.com/lowRISC/ibex
>>>
>>> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
>>> Reviewed-by: Bin Meng <bin.meng@windriver.com>
>>> ---
>>> target/riscv/cpu.h | 1 +
>>> target/riscv/cpu.c | 10 ++++++++++
>>> 2 files changed, 11 insertions(+)
>>>
>>> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>>> index d0e7f5b9c5..8733d7467f 100644
>>> --- a/target/riscv/cpu.h
>>> +++ b/target/riscv/cpu.h
>>> @@ -35,6 +35,7 @@
>>> #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
>>> #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
>>> #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
>>> +#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
>>> #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
>>> #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
>>> #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
>>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>>> index 5eb3c02735..eb2bbc87ae 100644
>>> --- a/target/riscv/cpu.c
>>> +++ b/target/riscv/cpu.c
>>> @@ -156,6 +156,15 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
>>> set_feature(env, RISCV_FEATURE_PMP);
>>> }
>>>
>>> +static void rv32imcu_nommu_cpu_init(Object *obj)
>>> +{
>>> + CPURISCVState *env = &RISCV_CPU(obj)->env;
>>> + set_misa(env, RV32 | RVI | RVM | RVC | RVU);
>>> + set_priv_version(env, PRIV_VERSION_1_10_0);
>>> + set_resetvec(env, 0x8090);
>> Hi Alistair,
>>
>> I see all RISC-V cpus have an reset vector which acts as the first pc
>> when machine boots up.
>> However, the first pc is more like an attribute of a machine, not a cpu.
> In general it seems to be a CPU property. I assume that some CPUs
> would allow the reset vector to be selectable though, in which case it
> becomes a board property.
>
>> Another reason is that the cpu names are a combination of ISA.
>> Then the cpus from different vendors may have same ISA, with different
>> reset vectors.
>>
>> Do you think so?
> If you are worried about CPUs with different vectors we could always
> make it a property in the future and have boards override it. I don't
> think we need that yet (only 1 CPU is different) but it is an easy
> future change.
I think your are right. A cpu reset vector property is better. If there
is a conflict in the future,
we can add the property there.
Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
Zhiwei
> Alistair
>
>> Zhiwei
>>> + set_feature(env, RISCV_FEATURE_PMP);
>>> +}
>>> +
>>> static void rv32imacu_nommu_cpu_init(Object *obj)
>>> {
>>> CPURISCVState *env = &RISCV_CPU(obj)->env;
>>> @@ -619,6 +628,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>>> DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
>>> #if defined(TARGET_RISCV32)
>>> DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init),
>>> + DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32imcu_nommu_cpu_init),
>>> DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
>>> DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init),
>>> DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init),
>>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU
2020-05-27 1:58 ` LIU Zhiwei
@ 2020-05-27 16:44 ` Alistair Francis
0 siblings, 0 replies; 21+ messages in thread
From: Alistair Francis @ 2020-05-27 16:44 UTC (permalink / raw)
To: LIU Zhiwei
Cc: open list:RISC-V, qemu-devel@nongnu.org Developers,
Alistair Francis, Palmer Dabbelt, Bin Meng,
Philippe Mathieu-Daudé
On Tue, May 26, 2020 at 6:58 PM LIU Zhiwei <zhiwei_liu@c-sky.com> wrote:
>
>
>
> On 2020/5/27 1:12, Alistair Francis wrote:
> > On Fri, May 22, 2020 at 12:51 AM LIU Zhiwei <zhiwei_liu@c-sky.com> wrote:
> >>
> >>
> >> On 2020/5/20 5:31, Alistair Francis wrote:
> >>> Ibex is a small and efficient, 32-bit, in-order RISC-V core with
> >>> a 2-stage pipeline that implements the RV32IMC instruction set
> >>> architecture.
> >>>
> >>> For more details on lowRISC see here:
> >>> https://github.com/lowRISC/ibex
> >>>
> >>> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> >>> Reviewed-by: Bin Meng <bin.meng@windriver.com>
> >>> ---
> >>> target/riscv/cpu.h | 1 +
> >>> target/riscv/cpu.c | 10 ++++++++++
> >>> 2 files changed, 11 insertions(+)
> >>>
> >>> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >>> index d0e7f5b9c5..8733d7467f 100644
> >>> --- a/target/riscv/cpu.h
> >>> +++ b/target/riscv/cpu.h
> >>> @@ -35,6 +35,7 @@
> >>> #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
> >>> #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
> >>> #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
> >>> +#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
> >>> #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
> >>> #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
> >>> #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
> >>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >>> index 5eb3c02735..eb2bbc87ae 100644
> >>> --- a/target/riscv/cpu.c
> >>> +++ b/target/riscv/cpu.c
> >>> @@ -156,6 +156,15 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
> >>> set_feature(env, RISCV_FEATURE_PMP);
> >>> }
> >>>
> >>> +static void rv32imcu_nommu_cpu_init(Object *obj)
> >>> +{
> >>> + CPURISCVState *env = &RISCV_CPU(obj)->env;
> >>> + set_misa(env, RV32 | RVI | RVM | RVC | RVU);
> >>> + set_priv_version(env, PRIV_VERSION_1_10_0);
> >>> + set_resetvec(env, 0x8090);
> >> Hi Alistair,
> >>
> >> I see all RISC-V cpus have an reset vector which acts as the first pc
> >> when machine boots up.
> >> However, the first pc is more like an attribute of a machine, not a cpu.
> > In general it seems to be a CPU property. I assume that some CPUs
> > would allow the reset vector to be selectable though, in which case it
> > becomes a board property.
> >
> >> Another reason is that the cpu names are a combination of ISA.
> >> Then the cpus from different vendors may have same ISA, with different
> >> reset vectors.
> >>
> >> Do you think so?
> > If you are worried about CPUs with different vectors we could always
> > make it a property in the future and have boards override it. I don't
> > think we need that yet (only 1 CPU is different) but it is an easy
> > future change.
> I think your are right. A cpu reset vector property is better. If there
> is a conflict in the future,
> we can add the property there.
>
> Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
Great! Thanks :)
Alistair
>
> Zhiwei
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v3 4/9] riscv: Initial commit of OpenTitan machine
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
` (2 preceding siblings ...)
2020-05-19 21:31 ` [PATCH v3 3/9] target/riscv: Add the lowRISC Ibex CPU Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-19 21:31 ` [PATCH v3 5/9] hw/char: Initial commit of Ibex UART Alistair Francis
` (4 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
This adds a barebone OpenTitan machine to QEMU.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
---
default-configs/riscv32-softmmu.mak | 1 +
default-configs/riscv64-softmmu.mak | 11 +-
include/hw/riscv/opentitan.h | 63 +++++++++++
hw/riscv/opentitan.c | 169 ++++++++++++++++++++++++++++
MAINTAINERS | 9 ++
hw/riscv/Kconfig | 5 +
hw/riscv/Makefile.objs | 1 +
7 files changed, 258 insertions(+), 1 deletion(-)
create mode 100644 include/hw/riscv/opentitan.h
create mode 100644 hw/riscv/opentitan.c
diff --git a/default-configs/riscv32-softmmu.mak b/default-configs/riscv32-softmmu.mak
index 1ae077ed87..94a236c9c2 100644
--- a/default-configs/riscv32-softmmu.mak
+++ b/default-configs/riscv32-softmmu.mak
@@ -10,3 +10,4 @@ CONFIG_SPIKE=y
CONFIG_SIFIVE_E=y
CONFIG_SIFIVE_U=y
CONFIG_RISCV_VIRT=y
+CONFIG_OPENTITAN=y
diff --git a/default-configs/riscv64-softmmu.mak b/default-configs/riscv64-softmmu.mak
index 235c6f473f..aaf6d735bb 100644
--- a/default-configs/riscv64-softmmu.mak
+++ b/default-configs/riscv64-softmmu.mak
@@ -1,3 +1,12 @@
# Default configuration for riscv64-softmmu
-include riscv32-softmmu.mak
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+
+# Boards:
+#
+CONFIG_SPIKE=y
+CONFIG_SIFIVE_E=y
+CONFIG_SIFIVE_U=y
+CONFIG_RISCV_VIRT=y
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
new file mode 100644
index 0000000000..15a3d87ed0
--- /dev/null
+++ b/include/hw/riscv/opentitan.h
@@ -0,0 +1,63 @@
+/*
+ * QEMU RISC-V Board Compatible with OpenTitan FPGA platform
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_OPENTITAN_H
+#define HW_OPENTITAN_H
+
+#include "hw/riscv/riscv_hart.h"
+
+#define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
+#define RISCV_IBEX_SOC(obj) \
+ OBJECT_CHECK(LowRISCIbexSoCState, (obj), TYPE_RISCV_IBEX_SOC)
+
+typedef struct LowRISCIbexSoCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ RISCVHartArrayState cpus;
+ MemoryRegion flash_mem;
+ MemoryRegion rom;
+} LowRISCIbexSoCState;
+
+typedef struct OpenTitanState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ LowRISCIbexSoCState soc;
+} OpenTitanState;
+
+enum {
+ IBEX_ROM,
+ IBEX_RAM,
+ IBEX_FLASH,
+ IBEX_UART,
+ IBEX_GPIO,
+ IBEX_SPI,
+ IBEX_FLASH_CTRL,
+ IBEX_RV_TIMER,
+ IBEX_AES,
+ IBEX_HMAC,
+ IBEX_PLIC,
+ IBEX_PINMUX,
+ IBEX_ALERT_HANDLER,
+ IBEX_USBDEV,
+};
+
+#endif
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
new file mode 100644
index 0000000000..c00f0720ab
--- /dev/null
+++ b/hw/riscv/opentitan.c
@@ -0,0 +1,169 @@
+/*
+ * QEMU RISC-V Board Compatible with OpenTitan FPGA platform
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * Provides a board compatible with the OpenTitan FPGA platform:
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/riscv/opentitan.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/misc/unimp.h"
+#include "hw/riscv/boot.h"
+#include "exec/address-spaces.h"
+
+static const struct MemmapEntry {
+ hwaddr base;
+ hwaddr size;
+} ibex_memmap[] = {
+ [IBEX_ROM] = { 0x00008000, 0xc000 },
+ [IBEX_RAM] = { 0x10000000, 0x10000 },
+ [IBEX_FLASH] = { 0x20000000, 0x80000 },
+ [IBEX_UART] = { 0x40000000, 0x10000 },
+ [IBEX_GPIO] = { 0x40010000, 0x10000 },
+ [IBEX_SPI] = { 0x40020000, 0x10000 },
+ [IBEX_FLASH_CTRL] = { 0x40030000, 0x10000 },
+ [IBEX_PINMUX] = { 0x40070000, 0x10000 },
+ [IBEX_RV_TIMER] = { 0x40080000, 0x10000 },
+ [IBEX_PLIC] = { 0x40090000, 0x10000 },
+ [IBEX_AES] = { 0x40110000, 0x10000 },
+ [IBEX_HMAC] = { 0x40120000, 0x10000 },
+ [IBEX_ALERT_HANDLER] = { 0x40130000, 0x10000 },
+ [IBEX_USBDEV] = { 0x40150000, 0x10000 }
+};
+
+static void riscv_opentitan_init(MachineState *machine)
+{
+ const struct MemmapEntry *memmap = ibex_memmap;
+ OpenTitanState *s = g_new0(OpenTitanState, 1);
+ MemoryRegion *sys_mem = get_system_memory();
+ MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+
+ /* Initialize SoC */
+ object_initialize_child(OBJECT(machine), "soc", &s->soc,
+ sizeof(s->soc), TYPE_RISCV_IBEX_SOC,
+ &error_abort, NULL);
+ object_property_set_bool(OBJECT(&s->soc), true, "realized",
+ &error_abort);
+
+ memory_region_init_ram(main_mem, NULL, "riscv.lowrisc.ibex.ram",
+ memmap[IBEX_RAM].size, &error_fatal);
+ memory_region_add_subregion(sys_mem,
+ memmap[IBEX_RAM].base, main_mem);
+
+
+ if (machine->firmware) {
+ riscv_load_firmware(machine->firmware, memmap[IBEX_RAM].base, NULL);
+ }
+
+ if (machine->kernel_filename) {
+ riscv_load_kernel(machine->kernel_filename, NULL);
+ }
+}
+
+static void riscv_opentitan_machine_init(MachineClass *mc)
+{
+ mc->desc = "RISC-V Board compatible with OpenTitan";
+ mc->init = riscv_opentitan_init;
+ mc->max_cpus = 1;
+ mc->default_cpu_type = TYPE_RISCV_CPU_IBEX;
+}
+
+DEFINE_MACHINE("opentitan", riscv_opentitan_machine_init)
+
+static void riscv_lowrisc_ibex_soc_init(Object *obj)
+{
+ LowRISCIbexSoCState *s = RISCV_IBEX_SOC(obj);
+
+ object_initialize_child(obj, "cpus", &s->cpus,
+ sizeof(s->cpus), TYPE_RISCV_HART_ARRAY,
+ &error_abort, NULL);
+}
+
+static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
+{
+ const struct MemmapEntry *memmap = ibex_memmap;
+ MachineState *ms = MACHINE(qdev_get_machine());
+ LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc);
+ MemoryRegion *sys_mem = get_system_memory();
+
+ object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type",
+ &error_abort);
+ object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts",
+ &error_abort);
+ object_property_set_bool(OBJECT(&s->cpus), true, "realized",
+ &error_abort);
+
+ /* Boot ROM */
+ memory_region_init_rom(&s->rom, OBJECT(dev_soc), "riscv.lowrisc.ibex.rom",
+ memmap[IBEX_ROM].size, &error_fatal);
+ memory_region_add_subregion(sys_mem,
+ memmap[IBEX_ROM].base, &s->rom);
+
+ /* Flash memory */
+ memory_region_init_rom(&s->flash_mem, OBJECT(dev_soc), "riscv.lowrisc.ibex.flash",
+ memmap[IBEX_FLASH].size, &error_fatal);
+ memory_region_add_subregion(sys_mem, memmap[IBEX_FLASH].base,
+ &s->flash_mem);
+
+ create_unimplemented_device("riscv.lowrisc.ibex.uart",
+ memmap[IBEX_UART].base, memmap[IBEX_UART].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.gpio",
+ memmap[IBEX_GPIO].base, memmap[IBEX_GPIO].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.spi",
+ memmap[IBEX_SPI].base, memmap[IBEX_SPI].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl",
+ memmap[IBEX_FLASH_CTRL].base, memmap[IBEX_FLASH_CTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.rv_timer",
+ memmap[IBEX_RV_TIMER].base, memmap[IBEX_RV_TIMER].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.aes",
+ memmap[IBEX_AES].base, memmap[IBEX_AES].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.hmac",
+ memmap[IBEX_HMAC].base, memmap[IBEX_HMAC].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.plic",
+ memmap[IBEX_PLIC].base, memmap[IBEX_PLIC].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
+ memmap[IBEX_PINMUX].base, memmap[IBEX_PINMUX].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.alert_handler",
+ memmap[IBEX_ALERT_HANDLER].base, memmap[IBEX_ALERT_HANDLER].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.USBDEV",
+ memmap[IBEX_USBDEV].base, memmap[IBEX_USBDEV].size);
+}
+
+static void riscv_lowrisc_ibex_soc_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = riscv_lowrisc_ibex_soc_realize;
+ /* Reason: Uses serial_hds in realize function, thus can't be used twice */
+ dc->user_creatable = false;
+}
+
+static const TypeInfo riscv_lowrisc_ibex_soc_type_info = {
+ .name = TYPE_RISCV_IBEX_SOC,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(LowRISCIbexSoCState),
+ .instance_init = riscv_lowrisc_ibex_soc_init,
+ .class_init = riscv_lowrisc_ibex_soc_class_init,
+};
+
+static void riscv_lowrisc_ibex_soc_register_types(void)
+{
+ type_register_static(&riscv_lowrisc_ibex_soc_type_info);
+}
+
+type_init(riscv_lowrisc_ibex_soc_register_types)
diff --git a/MAINTAINERS b/MAINTAINERS
index 47ef3139e6..a5f6aaa266 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1230,6 +1230,15 @@ F: pc-bios/canyonlands.dt[sb]
F: pc-bios/u-boot-sam460ex-20100605.bin
F: roms/u-boot-sam460ex
+RISC-V Machines
+---------------
+OpenTitan
+M: Alistair Francis <Alistair.Francis@wdc.com>
+L: qemu-riscv@nongnu.org
+S: Supported
+F: hw/riscv/opentitan.c
+F: include/hw/riscv/opentitan.h
+
SH4 Machines
------------
R2D
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index ff9fbe958a..94d19571f7 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -27,6 +27,11 @@ config SPIKE
select HTIF
select SIFIVE
+config OPENTITAN
+ bool
+ select HART
+ select UNIMP
+
config RISCV_VIRT
bool
imply PCI_DEVICES
diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs
index fc3c6dd7c8..57cc708f5d 100644
--- a/hw/riscv/Makefile.objs
+++ b/hw/riscv/Makefile.objs
@@ -1,6 +1,7 @@
obj-y += boot.o
obj-$(CONFIG_SPIKE) += riscv_htif.o
obj-$(CONFIG_HART) += riscv_hart.o
+obj-$(CONFIG_OPENTITAN) += opentitan.o
obj-$(CONFIG_SIFIVE_E) += sifive_e.o
obj-$(CONFIG_SIFIVE_E) += sifive_e_prci.o
obj-$(CONFIG_SIFIVE) += sifive_clint.o
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v3 5/9] hw/char: Initial commit of Ibex UART
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
` (3 preceding siblings ...)
2020-05-19 21:31 ` [PATCH v3 4/9] riscv: Initial commit of OpenTitan machine Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-19 21:31 ` [PATCH v3 6/9] hw/intc: Initial commit of lowRISC Ibex PLIC Alistair Francis
` (3 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
This is the initial commit of the Ibex UART device. Serial TX is
working, while RX has been implemeneted but untested.
This is based on the documentation from:
https://docs.opentitan.org/hw/ip/uart/doc/
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
include/hw/char/ibex_uart.h | 110 ++++++++
hw/char/ibex_uart.c | 492 ++++++++++++++++++++++++++++++++++++
MAINTAINERS | 2 +
hw/char/Makefile.objs | 1 +
hw/riscv/Kconfig | 4 +
5 files changed, 609 insertions(+)
create mode 100644 include/hw/char/ibex_uart.h
create mode 100644 hw/char/ibex_uart.c
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
new file mode 100644
index 0000000000..2bec772615
--- /dev/null
+++ b/include/hw/char/ibex_uart.h
@@ -0,0 +1,110 @@
+/*
+ * QEMU lowRISC Ibex UART device
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_IBEX_UART_H
+#define HW_IBEX_UART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qemu/timer.h"
+
+#define IBEX_UART_INTR_STATE 0x00
+ #define INTR_STATE_TX_WATERMARK (1 << 0)
+ #define INTR_STATE_RX_WATERMARK (1 << 1)
+ #define INTR_STATE_TX_EMPTY (1 << 2)
+ #define INTR_STATE_RX_OVERFLOW (1 << 3)
+#define IBEX_UART_INTR_ENABLE 0x04
+#define IBEX_UART_INTR_TEST 0x08
+
+#define IBEX_UART_CTRL 0x0c
+ #define UART_CTRL_TX_ENABLE (1 << 0)
+ #define UART_CTRL_RX_ENABLE (1 << 1)
+ #define UART_CTRL_NF (1 << 2)
+ #define UART_CTRL_SLPBK (1 << 4)
+ #define UART_CTRL_LLPBK (1 << 5)
+ #define UART_CTRL_PARITY_EN (1 << 6)
+ #define UART_CTRL_PARITY_ODD (1 << 7)
+ #define UART_CTRL_RXBLVL (3 << 8)
+ #define UART_CTRL_NCO (0xFFFF << 16)
+
+#define IBEX_UART_STATUS 0x10
+ #define UART_STATUS_TXFULL (1 << 0)
+ #define UART_STATUS_RXFULL (1 << 1)
+ #define UART_STATUS_TXEMPTY (1 << 2)
+ #define UART_STATUS_RXIDLE (1 << 4)
+ #define UART_STATUS_RXEMPTY (1 << 5)
+
+#define IBEX_UART_RDATA 0x14
+#define IBEX_UART_WDATA 0x18
+
+#define IBEX_UART_FIFO_CTRL 0x1c
+ #define FIFO_CTRL_RXRST (1 << 0)
+ #define FIFO_CTRL_TXRST (1 << 1)
+ #define FIFO_CTRL_RXILVL (7 << 2)
+ #define FIFO_CTRL_RXILVL_SHIFT (2)
+ #define FIFO_CTRL_TXILVL (3 << 5)
+ #define FIFO_CTRL_TXILVL_SHIFT (5)
+
+#define IBEX_UART_FIFO_STATUS 0x20
+#define IBEX_UART_OVRD 0x24
+#define IBEX_UART_VAL 0x28
+#define IBEX_UART_TIMEOUT_CTRL 0x2c
+
+#define IBEX_UART_TX_FIFO_SIZE 16
+
+#define TYPE_IBEX_UART "ibex-uart"
+#define IBEX_UART(obj) \
+ OBJECT_CHECK(IbexUartState, (obj), TYPE_IBEX_UART)
+
+typedef struct {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint8_t tx_fifo[IBEX_UART_TX_FIFO_SIZE];
+ uint32_t tx_level;
+
+ QEMUTimer *fifo_trigger_handle;
+ uint64_t char_tx_time;
+
+ uint32_t uart_intr_state;
+ uint32_t uart_intr_enable;
+ uint32_t uart_ctrl;
+ uint32_t uart_status;
+ uint32_t uart_rdata;
+ uint32_t uart_fifo_ctrl;
+ uint32_t uart_fifo_status;
+ uint32_t uart_ovrd;
+ uint32_t uart_val;
+ uint32_t uart_timeout_ctrl;
+
+ CharBackend chr;
+ qemu_irq tx_watermark;
+ qemu_irq rx_watermark;
+ qemu_irq tx_empty;
+ qemu_irq rx_overflow;
+} IbexUartState;
+#endif /* HW_IBEX_UART_H */
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
new file mode 100644
index 0000000000..c416325d73
--- /dev/null
+++ b/hw/char/ibex_uart.c
@@ -0,0 +1,492 @@
+/*
+ * QEMU lowRISC Ibex UART device
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * For details check the documentation here:
+ * https://docs.opentitan.org/hw/ip/uart/doc/
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/ibex_uart.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+
+static void ibex_uart_update_irqs(IbexUartState *s)
+{
+ if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_TX_WATERMARK) {
+ qemu_set_irq(s->tx_watermark, 1);
+ } else {
+ qemu_set_irq(s->tx_watermark, 0);
+ }
+
+ if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_RX_WATERMARK) {
+ qemu_set_irq(s->rx_watermark, 1);
+ } else {
+ qemu_set_irq(s->rx_watermark, 0);
+ }
+
+ if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_TX_EMPTY) {
+ qemu_set_irq(s->tx_empty, 1);
+ } else {
+ qemu_set_irq(s->tx_empty, 0);
+ }
+
+ if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_RX_OVERFLOW) {
+ qemu_set_irq(s->rx_overflow, 1);
+ } else {
+ qemu_set_irq(s->rx_overflow, 0);
+ }
+}
+
+static int ibex_uart_can_receive(void *opaque)
+{
+ IbexUartState *s = opaque;
+
+ if (s->uart_ctrl & UART_CTRL_RX_ENABLE) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ IbexUartState *s = opaque;
+ uint8_t rx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_RXILVL)
+ >> FIFO_CTRL_RXILVL_SHIFT;
+
+ s->uart_rdata = *buf;
+
+ s->uart_status &= ~UART_STATUS_RXIDLE;
+ s->uart_status &= ~UART_STATUS_RXEMPTY;
+
+ if (size > rx_fifo_level) {
+ s->uart_intr_state |= INTR_STATE_RX_WATERMARK;
+ }
+
+ ibex_uart_update_irqs(s);
+}
+
+static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
+ void *opaque)
+{
+ IbexUartState *s = opaque;
+ uint8_t tx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_TXILVL)
+ >> FIFO_CTRL_TXILVL_SHIFT;
+ int ret;
+
+ /* instant drain the fifo when there's no back-end */
+ if (!qemu_chr_fe_backend_connected(&s->chr)) {
+ s->tx_level = 0;
+ return FALSE;
+ }
+
+ if (!s->tx_level) {
+ s->uart_status &= UART_STATUS_TXFULL;
+ s->uart_status |= UART_STATUS_TXEMPTY;
+ s->uart_intr_state |= INTR_STATE_TX_EMPTY;
+ s->uart_intr_state &= ~INTR_STATE_TX_WATERMARK;
+ ibex_uart_update_irqs(s);
+ return FALSE;
+ }
+
+ ret = qemu_chr_fe_write(&s->chr, s->tx_fifo, s->tx_level);
+
+ if (ret >= 0) {
+ s->tx_level -= ret;
+ memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_level);
+ }
+
+ if (s->tx_level) {
+ guint r = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
+ ibex_uart_xmit, s);
+ if (!r) {
+ s->tx_level = 0;
+ return FALSE;
+ }
+ }
+
+ /* Clear the TX Full bit */
+ if (s->tx_level != IBEX_UART_TX_FIFO_SIZE) {
+ s->uart_status &= ~UART_STATUS_TXFULL;
+ }
+
+ /* Disable the TX_WATERMARK IRQ */
+ if (s->tx_level < tx_fifo_level) {
+ s->uart_intr_state &= ~INTR_STATE_TX_WATERMARK;
+ }
+
+ /* Set TX empty */
+ if (s->tx_level == 0) {
+ s->uart_status |= UART_STATUS_TXEMPTY;
+ s->uart_intr_state |= INTR_STATE_TX_EMPTY;
+ }
+
+ ibex_uart_update_irqs(s);
+ return FALSE;
+}
+
+static void uart_write_tx_fifo(IbexUartState *s, const uint8_t *buf,
+ int size)
+{
+ uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ uint8_t tx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_TXILVL)
+ >> FIFO_CTRL_TXILVL_SHIFT;
+
+ if (size > IBEX_UART_TX_FIFO_SIZE - s->tx_level) {
+ size = IBEX_UART_TX_FIFO_SIZE - s->tx_level;
+ qemu_log_mask(LOG_GUEST_ERROR, "ibex_uart: TX FIFO overflow");
+ }
+
+ memcpy(s->tx_fifo + s->tx_level, buf, size);
+ s->tx_level += size;
+
+ if (s->tx_level > 0) {
+ s->uart_status &= ~UART_STATUS_TXEMPTY;
+ }
+
+ if (s->tx_level >= tx_fifo_level) {
+ s->uart_intr_state |= INTR_STATE_TX_WATERMARK;
+ ibex_uart_update_irqs(s);
+ }
+
+ if (s->tx_level == IBEX_UART_TX_FIFO_SIZE) {
+ s->uart_status |= UART_STATUS_TXFULL;
+ }
+
+ timer_mod(s->fifo_trigger_handle, current_time +
+ (s->char_tx_time * 4));
+}
+
+static void ibex_uart_reset(DeviceState *dev)
+{
+ IbexUartState *s = IBEX_UART(dev);
+
+ s->uart_intr_state = 0x00000000;
+ s->uart_intr_state = 0x00000000;
+ s->uart_intr_enable = 0x00000000;
+ s->uart_ctrl = 0x00000000;
+ s->uart_status = 0x0000003c;
+ s->uart_rdata = 0x00000000;
+ s->uart_fifo_ctrl = 0x00000000;
+ s->uart_fifo_status = 0x00000000;
+ s->uart_ovrd = 0x00000000;
+ s->uart_val = 0x00000000;
+ s->uart_timeout_ctrl = 0x00000000;
+
+ s->tx_level = 0;
+
+ s->char_tx_time = (NANOSECONDS_PER_SECOND / 230400) * 10;
+
+ ibex_uart_update_irqs(s);
+}
+
+static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ IbexUartState *s = opaque;
+ uint64_t retvalue = 0;
+
+ switch (addr) {
+ case IBEX_UART_INTR_STATE:
+ retvalue = s->uart_intr_state;
+ break;
+ case IBEX_UART_INTR_ENABLE:
+ retvalue = s->uart_intr_enable;
+ break;
+ case IBEX_UART_INTR_TEST:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: wdata is write only\n", __func__);
+ break;
+
+ case IBEX_UART_CTRL:
+ retvalue = s->uart_ctrl;
+ break;
+ case IBEX_UART_STATUS:
+ retvalue = s->uart_status;
+ break;
+
+ case IBEX_UART_RDATA:
+ retvalue = s->uart_rdata;
+ if (s->uart_ctrl & UART_CTRL_RX_ENABLE) {
+ qemu_chr_fe_accept_input(&s->chr);
+
+ s->uart_status |= UART_STATUS_RXIDLE;
+ s->uart_status |= UART_STATUS_RXEMPTY;
+ }
+ break;
+ case IBEX_UART_WDATA:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: wdata is write only\n", __func__);
+ break;
+
+ case IBEX_UART_FIFO_CTRL:
+ retvalue = s->uart_fifo_ctrl;
+ break;
+ case IBEX_UART_FIFO_STATUS:
+ retvalue = s->uart_fifo_status;
+
+ retvalue |= s->tx_level & 0x1F;
+
+ qemu_log_mask(LOG_UNIMP,
+ "%s: RX fifos are not supported\n", __func__);
+ break;
+
+ case IBEX_UART_OVRD:
+ retvalue = s->uart_ovrd;
+ qemu_log_mask(LOG_UNIMP,
+ "%s: ovrd is not supported\n", __func__);
+ break;
+ case IBEX_UART_VAL:
+ retvalue = s->uart_val;
+ qemu_log_mask(LOG_UNIMP,
+ "%s: val is not supported\n", __func__);
+ break;
+ case IBEX_UART_TIMEOUT_CTRL:
+ retvalue = s->uart_timeout_ctrl;
+ qemu_log_mask(LOG_UNIMP,
+ "%s: timeout_ctrl is not supported\n", __func__);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+ return 0;
+ }
+
+ return retvalue;
+}
+
+static void ibex_uart_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ IbexUartState *s = opaque;
+ uint32_t value = val64;
+
+ switch (addr) {
+ case IBEX_UART_INTR_STATE:
+ /* Write 1 clear */
+ s->uart_intr_state &= ~value;
+ ibex_uart_update_irqs(s);
+ break;
+ case IBEX_UART_INTR_ENABLE:
+ s->uart_intr_enable = value;
+ ibex_uart_update_irqs(s);
+ break;
+ case IBEX_UART_INTR_TEST:
+ s->uart_intr_state |= value;
+ ibex_uart_update_irqs(s);
+ break;
+
+ case IBEX_UART_CTRL:
+ s->uart_ctrl = value;
+
+ if (value & UART_CTRL_NF) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: UART_CTRL_NF is not supported\n", __func__);
+ }
+ if (value & UART_CTRL_SLPBK) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: UART_CTRL_SLPBK is not supported\n", __func__);
+ }
+ if (value & UART_CTRL_LLPBK) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: UART_CTRL_LLPBK is not supported\n", __func__);
+ }
+ if (value & UART_CTRL_PARITY_EN) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: UART_CTRL_PARITY_EN is not supported\n",
+ __func__);
+ }
+ if (value & UART_CTRL_PARITY_ODD) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: UART_CTRL_PARITY_ODD is not supported\n",
+ __func__);
+ }
+ if (value & UART_CTRL_RXBLVL) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: UART_CTRL_RXBLVL is not supported\n", __func__);
+ }
+ if (value & UART_CTRL_NCO) {
+ uint64_t baud = ((value & UART_CTRL_NCO) >> 16);
+ baud *= 1000;
+ baud /= 2 ^ 20;
+
+ s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10;
+ }
+ break;
+ case IBEX_UART_STATUS:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: status is read only\n", __func__);
+ break;
+
+ case IBEX_UART_RDATA:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: rdata is read only\n", __func__);
+ break;
+ case IBEX_UART_WDATA:
+ uart_write_tx_fifo(s, (uint8_t *) &value, 1);
+ break;
+
+ case IBEX_UART_FIFO_CTRL:
+ s->uart_fifo_ctrl = value;
+
+ if (value & FIFO_CTRL_RXRST) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: RX fifos are not supported\n", __func__);
+ }
+ if (value & FIFO_CTRL_TXRST) {
+ s->tx_level = 0;
+ }
+ break;
+ case IBEX_UART_FIFO_STATUS:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: fifo_status is read only\n", __func__);
+ break;
+
+ case IBEX_UART_OVRD:
+ s->uart_ovrd = value;
+ qemu_log_mask(LOG_UNIMP,
+ "%s: ovrd is not supported\n", __func__);
+ break;
+ case IBEX_UART_VAL:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: val is read only\n", __func__);
+ break;
+ case IBEX_UART_TIMEOUT_CTRL:
+ s->uart_timeout_ctrl = value;
+ qemu_log_mask(LOG_UNIMP,
+ "%s: timeout_ctrl is not supported\n", __func__);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+ }
+}
+
+static void fifo_trigger_update(void *opaque)
+{
+ IbexUartState *s = opaque;
+
+ if (s->uart_ctrl & UART_CTRL_TX_ENABLE) {
+ ibex_uart_xmit(NULL, G_IO_OUT, s);
+ }
+}
+
+static const MemoryRegionOps ibex_uart_ops = {
+ .read = ibex_uart_read,
+ .write = ibex_uart_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+};
+
+static int cadence_uart_post_load(void *opaque, int version_id)
+{
+ IbexUartState *s = opaque;
+
+ ibex_uart_update_irqs(s);
+ return 0;
+}
+
+static const VMStateDescription vmstate_ibex_uart = {
+ .name = TYPE_IBEX_UART,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = cadence_uart_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(tx_fifo, IbexUartState,
+ IBEX_UART_TX_FIFO_SIZE),
+ VMSTATE_UINT32(tx_level, IbexUartState),
+ VMSTATE_UINT64(char_tx_time, IbexUartState),
+ VMSTATE_TIMER_PTR(fifo_trigger_handle, IbexUartState),
+ VMSTATE_UINT32(uart_intr_state, IbexUartState),
+ VMSTATE_UINT32(uart_intr_enable, IbexUartState),
+ VMSTATE_UINT32(uart_ctrl, IbexUartState),
+ VMSTATE_UINT32(uart_status, IbexUartState),
+ VMSTATE_UINT32(uart_rdata, IbexUartState),
+ VMSTATE_UINT32(uart_fifo_ctrl, IbexUartState),
+ VMSTATE_UINT32(uart_fifo_status, IbexUartState),
+ VMSTATE_UINT32(uart_ovrd, IbexUartState),
+ VMSTATE_UINT32(uart_val, IbexUartState),
+ VMSTATE_UINT32(uart_timeout_ctrl, IbexUartState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property ibex_uart_properties[] = {
+ DEFINE_PROP_CHR("chardev", IbexUartState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ibex_uart_init(Object *obj)
+{
+ IbexUartState *s = IBEX_UART(obj);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark);
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rx_watermark);
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_empty);
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rx_overflow);
+
+ memory_region_init_io(&s->mmio, obj, &ibex_uart_ops, s,
+ TYPE_IBEX_UART, 0x400);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void ibex_uart_realize(DeviceState *dev, Error **errp)
+{
+ IbexUartState *s = IBEX_UART(dev);
+
+ s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ fifo_trigger_update, s);
+
+ qemu_chr_fe_set_handlers(&s->chr, ibex_uart_can_receive,
+ ibex_uart_receive, NULL, NULL,
+ s, NULL, true);
+}
+
+static void ibex_uart_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = ibex_uart_reset;
+ dc->realize = ibex_uart_realize;
+ dc->vmsd = &vmstate_ibex_uart;
+ device_class_set_props(dc, ibex_uart_properties);
+}
+
+static const TypeInfo ibex_uart_info = {
+ .name = TYPE_IBEX_UART,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IbexUartState),
+ .instance_init = ibex_uart_init,
+ .class_init = ibex_uart_class_init,
+};
+
+static void ibex_uart_register_types(void)
+{
+ type_register_static(&ibex_uart_info);
+}
+
+type_init(ibex_uart_register_types)
diff --git a/MAINTAINERS b/MAINTAINERS
index a5f6aaa266..7d27a44d15 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1237,7 +1237,9 @@ M: Alistair Francis <Alistair.Francis@wdc.com>
L: qemu-riscv@nongnu.org
S: Supported
F: hw/riscv/opentitan.c
+F: hw/char/ibex_uart.c
F: include/hw/riscv/opentitan.h
+F: include/hw/char/ibex_uart.h
SH4 Machines
------------
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 9e9a6c1aff..633996be5b 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-$(CONFIG_VIRTIO_SERIAL) += virtio-console.o
common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
common-obj-$(CONFIG_XEN) += xen_console.o
common-obj-$(CONFIG_CADENCE) += cadence_uart.o
+common-obj-$(CONFIG_IBEX) += ibex_uart.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_uart.o
common-obj-$(CONFIG_COLDFIRE) += mcf_uart.o
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 94d19571f7..28947ef3e0 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -4,6 +4,9 @@ config HTIF
config HART
bool
+config IBEX
+ bool
+
config SIFIVE
bool
select MSI_NONBROKEN
@@ -29,6 +32,7 @@ config SPIKE
config OPENTITAN
bool
+ select IBEX
select HART
select UNIMP
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v3 6/9] hw/intc: Initial commit of lowRISC Ibex PLIC
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
` (4 preceding siblings ...)
2020-05-19 21:31 ` [PATCH v3 5/9] hw/char: Initial commit of Ibex UART Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-19 21:31 ` [PATCH v3 7/9] riscv/opentitan: Connect the PLIC device Alistair Francis
` (2 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
The Ibex core contains a PLIC that although similar to the RISC-V spec
is not RISC-V spec compliant.
This patch implements a Ibex PLIC in a somewhat generic way.
As the current RISC-V PLIC needs tidying up, my hope is that as the Ibex
PLIC move towards spec compliance this PLIC implementation can be
updated until it can replace the current PLIC.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
include/hw/intc/ibex_plic.h | 63 +++++++++
hw/intc/ibex_plic.c | 261 ++++++++++++++++++++++++++++++++++++
MAINTAINERS | 2 +
hw/intc/Makefile.objs | 1 +
4 files changed, 327 insertions(+)
create mode 100644 include/hw/intc/ibex_plic.h
create mode 100644 hw/intc/ibex_plic.c
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
new file mode 100644
index 0000000000..ddc7909903
--- /dev/null
+++ b/include/hw/intc/ibex_plic.h
@@ -0,0 +1,63 @@
+/*
+ * QEMU RISC-V lowRISC Ibex PLIC
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_IBEX_PLIC_H
+#define HW_IBEX_PLIC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_IBEX_PLIC "ibex-plic"
+#define IBEX_PLIC(obj) \
+ OBJECT_CHECK(IbexPlicState, (obj), TYPE_IBEX_PLIC)
+
+typedef struct IbexPlicState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+
+ uint32_t *pending;
+ uint32_t *source;
+ uint32_t *priority;
+ uint32_t *enable;
+ uint32_t threshold;
+ uint32_t claim;
+
+ /* config */
+ uint32_t num_cpus;
+ uint32_t num_sources;
+
+ uint32_t pending_base;
+ uint32_t pending_num;
+
+ uint32_t source_base;
+ uint32_t source_num;
+
+ uint32_t priority_base;
+ uint32_t priority_num;
+
+ uint32_t enable_base;
+ uint32_t enable_num;
+
+ uint32_t threshold_base;
+
+ uint32_t claim_base;
+} IbexPlicState;
+
+#endif /* HW_IBEX_PLIC_H */
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
new file mode 100644
index 0000000000..41079518c6
--- /dev/null
+++ b/hw/intc/ibex_plic.c
@@ -0,0 +1,261 @@
+/*
+ * QEMU RISC-V lowRISC Ibex PLIC
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * Documentation avaliable: https://docs.opentitan.org/hw/ip/rv_plic/doc/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/qdev-properties.h"
+#include "hw/core/cpu.h"
+#include "hw/boards.h"
+#include "hw/pci/msi.h"
+#include "target/riscv/cpu_bits.h"
+#include "target/riscv/cpu.h"
+#include "hw/intc/ibex_plic.h"
+
+static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
+{
+ uint32_t end = base + (num * 0x04);
+
+ if (addr >= base && addr < end) {
+ return true;
+ }
+
+ return false;
+}
+
+static void ibex_plic_irqs_set_pending(IbexPlicState *s, int irq, bool level)
+{
+ int pending_num = irq / 32;
+
+ s->pending[pending_num] |= level << (irq % 32);
+}
+
+static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
+{
+ int i;
+
+ for (i = 0; i < s->pending_num; i++) {
+ uint32_t irq_num = ctz64(s->pending[i]) + (i * 32);
+
+ if (!(s->pending[i] & s->enable[i])) {
+ /* No pending and enabled IRQ */
+ continue;
+ }
+
+ if (s->priority[irq_num] > s->threshold) {
+ if (!s->claim) {
+ s->claim = irq_num;
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void ibex_plic_update(IbexPlicState *s)
+{
+ CPUState *cpu;
+ int level, i;
+
+ for (i = 0; i < s->num_cpus; i++) {
+ cpu = qemu_get_cpu(i);
+
+ if (!cpu) {
+ continue;
+ }
+
+ level = ibex_plic_irqs_pending(s, 0);
+
+ riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
+ }
+}
+
+static void ibex_plic_reset(DeviceState *dev)
+{
+ IbexPlicState *s = IBEX_PLIC(dev);
+
+ s->threshold = 0x00000000;
+ s->claim = 0x00000000;
+}
+
+static uint64_t ibex_plic_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ IbexPlicState *s = opaque;
+ int offset;
+ uint32_t ret = 0;
+
+ if (addr_between(addr, s->pending_base, s->pending_num)) {
+ offset = (addr - s->pending_base) / 4;
+ ret = s->pending[offset];
+ } else if (addr_between(addr, s->source_base, s->source_num)) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: Interrupt source mode not supported\n", __func__);
+ } else if (addr_between(addr, s->priority_base, s->priority_num)) {
+ offset = (addr - s->priority_base) / 4;
+ ret = s->priority[offset];
+ } else if (addr_between(addr, s->enable_base, s->enable_num)) {
+ offset = (addr - s->enable_base) / 4;
+ ret = s->enable[offset];
+ } else if (addr_between(addr, s->threshold_base, 1)) {
+ ret = s->threshold;
+ } else if (addr_between(addr, s->claim_base, 1)) {
+ int pending_num = s->claim / 32;
+ s->pending[pending_num] &= ~(1 << (s->claim % 32));
+
+ ret = s->claim;
+ }
+
+ return ret;
+}
+
+static void ibex_plic_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned int size)
+{
+ IbexPlicState *s = opaque;
+
+ if (addr_between(addr, s->pending_base, s->pending_num)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Pending registers are read only\n", __func__);
+ } else if (addr_between(addr, s->source_base, s->source_num)) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: Interrupt source mode not supported\n", __func__);
+ } else if (addr_between(addr, s->priority_base, s->priority_num)) {
+ uint32_t irq = ((addr - s->priority_base) >> 2) + 1;
+ s->priority[irq] = value & 7;
+ } else if (addr_between(addr, s->enable_base, s->enable_num)) {
+ uint32_t enable_reg = (addr - s->enable_base) / 4;
+
+ s->enable[enable_reg] = value;
+ } else if (addr_between(addr, s->threshold_base, 1)) {
+ s->threshold = value & 3;
+ } else if (addr_between(addr, s->claim_base, 1)) {
+ if (s->claim == value) {
+ /* Interrupt was completed */
+ s->claim = 0;
+ }
+ }
+
+ ibex_plic_update(s);
+}
+
+static const MemoryRegionOps ibex_plic_ops = {
+ .read = ibex_plic_read,
+ .write = ibex_plic_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4
+ }
+};
+
+static void ibex_plic_irq_request(void *opaque, int irq, int level)
+{
+ IbexPlicState *s = opaque;
+
+ ibex_plic_irqs_set_pending(s, irq, level > 0);
+ ibex_plic_update(s);
+}
+
+static Property ibex_plic_properties[] = {
+ DEFINE_PROP_UINT32("num-cpus", IbexPlicState, num_cpus, 1),
+ DEFINE_PROP_UINT32("num-sources", IbexPlicState, num_sources, 80),
+
+ DEFINE_PROP_UINT32("pending-base", IbexPlicState, pending_base, 0),
+ DEFINE_PROP_UINT32("pending-num", IbexPlicState, pending_num, 3),
+
+ DEFINE_PROP_UINT32("source-base", IbexPlicState, source_base, 0x0c),
+ DEFINE_PROP_UINT32("source-num", IbexPlicState, source_num, 3),
+
+ DEFINE_PROP_UINT32("priority-base", IbexPlicState, priority_base, 0x18),
+ DEFINE_PROP_UINT32("priority-num", IbexPlicState, priority_num, 80),
+
+ DEFINE_PROP_UINT32("enable-base", IbexPlicState, enable_base, 0x200),
+ DEFINE_PROP_UINT32("enable-num", IbexPlicState, enable_num, 3),
+
+ DEFINE_PROP_UINT32("threshold-base", IbexPlicState, threshold_base, 0x20c),
+
+ DEFINE_PROP_UINT32("claim-base", IbexPlicState, claim_base, 0x210),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ibex_plic_init(Object *obj)
+{
+ IbexPlicState *s = IBEX_PLIC(obj);
+
+ memory_region_init_io(&s->mmio, obj, &ibex_plic_ops, s,
+ TYPE_IBEX_PLIC, 0x400);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void ibex_plic_realize(DeviceState *dev, Error **errp)
+{
+ IbexPlicState *s = IBEX_PLIC(dev);
+ int i;
+
+ s->pending = g_new0(uint32_t, s->pending_num);
+ s->source = g_new0(uint32_t, s->source_num);
+ s->priority = g_new0(uint32_t, s->priority_num);
+ s->enable = g_new0(uint32_t, s->enable_num);
+
+ qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
+
+ /*
+ * We can't allow the supervisor to control SEIP as this would allow the
+ * supervisor to clear a pending external interrupt which will result in
+ * a lost interrupt in the case a PLIC is attached. The SEIP bit must be
+ * hardware controlled when a PLIC is attached.
+ */
+ MachineState *ms = MACHINE(qdev_get_machine());
+ unsigned int smp_cpus = ms->smp.cpus;
+ for (i = 0; i < smp_cpus; i++) {
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i));
+ if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
+ error_report("SEIP already claimed");
+ exit(1);
+ }
+ }
+
+ msi_nonbroken = true;
+}
+
+static void ibex_plic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = ibex_plic_reset;
+ device_class_set_props(dc, ibex_plic_properties);
+ dc->realize = ibex_plic_realize;
+}
+
+static const TypeInfo ibex_plic_info = {
+ .name = TYPE_IBEX_PLIC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IbexPlicState),
+ .instance_init = ibex_plic_init,
+ .class_init = ibex_plic_class_init,
+};
+
+static void ibex_plic_register_types(void)
+{
+ type_register_static(&ibex_plic_info);
+}
+
+type_init(ibex_plic_register_types)
diff --git a/MAINTAINERS b/MAINTAINERS
index 7d27a44d15..34b7c1745d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1238,8 +1238,10 @@ L: qemu-riscv@nongnu.org
S: Supported
F: hw/riscv/opentitan.c
F: hw/char/ibex_uart.c
+F: hw/intc/ibex_plic.c
F: include/hw/riscv/opentitan.h
F: include/hw/char/ibex_uart.h
+F: include/hw/intc/ibex_plic.h
SH4 Machines
------------
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index f726d87532..a61e6728fe 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -49,3 +49,4 @@ obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o
obj-$(CONFIG_MIPS_CPS) += mips_gic.o
obj-$(CONFIG_NIOS2) += nios2_iic.o
obj-$(CONFIG_OMPIC) += ompic.o
+obj-$(CONFIG_IBEX) += ibex_plic.o
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v3 7/9] riscv/opentitan: Connect the PLIC device
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
` (5 preceding siblings ...)
2020-05-19 21:31 ` [PATCH v3 6/9] hw/intc: Initial commit of lowRISC Ibex PLIC Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-20 6:03 ` Philippe Mathieu-Daudé
2020-05-19 21:31 ` [PATCH v3 8/9] riscv/opentitan: Connect the UART device Alistair Francis
2020-05-19 21:31 ` [PATCH v3 9/9] target/riscv: Use a smaller guess size for no-MMU PMP Alistair Francis
8 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
---
include/hw/riscv/opentitan.h | 3 +++
hw/riscv/opentitan.c | 19 +++++++++++++++++--
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
index 15a3d87ed0..8d6a09b696 100644
--- a/include/hw/riscv/opentitan.h
+++ b/include/hw/riscv/opentitan.h
@@ -20,6 +20,7 @@
#define HW_OPENTITAN_H
#include "hw/riscv/riscv_hart.h"
+#include "hw/intc/ibex_plic.h"
#define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
#define RISCV_IBEX_SOC(obj) \
@@ -31,6 +32,8 @@ typedef struct LowRISCIbexSoCState {
/*< public >*/
RISCVHartArrayState cpus;
+ IbexPlicState plic;
+
MemoryRegion flash_mem;
MemoryRegion rom;
} LowRISCIbexSoCState;
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index c00f0720ab..3926321d8c 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -25,6 +25,7 @@
#include "hw/misc/unimp.h"
#include "hw/riscv/boot.h"
#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
static const struct MemmapEntry {
hwaddr base;
@@ -92,6 +93,9 @@ static void riscv_lowrisc_ibex_soc_init(Object *obj)
object_initialize_child(obj, "cpus", &s->cpus,
sizeof(s->cpus), TYPE_RISCV_HART_ARRAY,
&error_abort, NULL);
+
+ sysbus_init_child_obj(obj, "plic", &s->plic,
+ sizeof(s->plic), TYPE_IBEX_PLIC);
}
static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
@@ -100,6 +104,9 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
MachineState *ms = MACHINE(qdev_get_machine());
LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc);
MemoryRegion *sys_mem = get_system_memory();
+ DeviceState *dev;
+ SysBusDevice *busdev;
+ Error *err = NULL;
object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type",
&error_abort);
@@ -120,6 +127,16 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
memory_region_add_subregion(sys_mem, memmap[IBEX_FLASH].base,
&s->flash_mem);
+ /* PLIC */
+ dev = DEVICE(&s->plic);
+ object_property_set_bool(OBJECT(&s->plic), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, memmap[IBEX_PLIC].base);
+
create_unimplemented_device("riscv.lowrisc.ibex.uart",
memmap[IBEX_UART].base, memmap[IBEX_UART].size);
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
@@ -134,8 +151,6 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
memmap[IBEX_AES].base, memmap[IBEX_AES].size);
create_unimplemented_device("riscv.lowrisc.ibex.hmac",
memmap[IBEX_HMAC].base, memmap[IBEX_HMAC].size);
- create_unimplemented_device("riscv.lowrisc.ibex.plic",
- memmap[IBEX_PLIC].base, memmap[IBEX_PLIC].size);
create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
memmap[IBEX_PINMUX].base, memmap[IBEX_PINMUX].size);
create_unimplemented_device("riscv.lowrisc.ibex.alert_handler",
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3 7/9] riscv/opentitan: Connect the PLIC device
2020-05-19 21:31 ` [PATCH v3 7/9] riscv/opentitan: Connect the PLIC device Alistair Francis
@ 2020-05-20 6:03 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-05-20 6:03 UTC (permalink / raw)
To: Alistair Francis, qemu-devel, qemu-riscv; +Cc: alistair23, bmeng.cn, palmer
On 5/19/20 11:31 PM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Bin Meng <bin.meng@windriver.com>
> ---
> include/hw/riscv/opentitan.h | 3 +++
> hw/riscv/opentitan.c | 19 +++++++++++++++++--
> 2 files changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
> index 15a3d87ed0..8d6a09b696 100644
> --- a/include/hw/riscv/opentitan.h
> +++ b/include/hw/riscv/opentitan.h
> @@ -20,6 +20,7 @@
> #define HW_OPENTITAN_H
>
> #include "hw/riscv/riscv_hart.h"
> +#include "hw/intc/ibex_plic.h"
>
> #define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
> #define RISCV_IBEX_SOC(obj) \
> @@ -31,6 +32,8 @@ typedef struct LowRISCIbexSoCState {
>
> /*< public >*/
> RISCVHartArrayState cpus;
> + IbexPlicState plic;
> +
> MemoryRegion flash_mem;
> MemoryRegion rom;
> } LowRISCIbexSoCState;
> diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
> index c00f0720ab..3926321d8c 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -25,6 +25,7 @@
> #include "hw/misc/unimp.h"
> #include "hw/riscv/boot.h"
> #include "exec/address-spaces.h"
> +#include "sysemu/sysemu.h"
>
> static const struct MemmapEntry {
> hwaddr base;
> @@ -92,6 +93,9 @@ static void riscv_lowrisc_ibex_soc_init(Object *obj)
> object_initialize_child(obj, "cpus", &s->cpus,
> sizeof(s->cpus), TYPE_RISCV_HART_ARRAY,
> &error_abort, NULL);
> +
> + sysbus_init_child_obj(obj, "plic", &s->plic,
> + sizeof(s->plic), TYPE_IBEX_PLIC);
> }
>
> static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
> @@ -100,6 +104,9 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
> MachineState *ms = MACHINE(qdev_get_machine());
> LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc);
> MemoryRegion *sys_mem = get_system_memory();
> + DeviceState *dev;
> + SysBusDevice *busdev;
> + Error *err = NULL;
>
> object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type",
> &error_abort);
> @@ -120,6 +127,16 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
> memory_region_add_subregion(sys_mem, memmap[IBEX_FLASH].base,
> &s->flash_mem);
>
> + /* PLIC */
> + dev = DEVICE(&s->plic);
> + object_property_set_bool(OBJECT(&s->plic), true, "realized", &err);
> + if (err != NULL) {
> + error_propagate(errp, err);
> + return;
> + }
> + busdev = SYS_BUS_DEVICE(dev);
> + sysbus_mmio_map(busdev, 0, memmap[IBEX_PLIC].base);
> +
> create_unimplemented_device("riscv.lowrisc.ibex.uart",
> memmap[IBEX_UART].base, memmap[IBEX_UART].size);
> create_unimplemented_device("riscv.lowrisc.ibex.gpio",
> @@ -134,8 +151,6 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
> memmap[IBEX_AES].base, memmap[IBEX_AES].size);
> create_unimplemented_device("riscv.lowrisc.ibex.hmac",
> memmap[IBEX_HMAC].base, memmap[IBEX_HMAC].size);
> - create_unimplemented_device("riscv.lowrisc.ibex.plic",
> - memmap[IBEX_PLIC].base, memmap[IBEX_PLIC].size);
> create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
> memmap[IBEX_PINMUX].base, memmap[IBEX_PINMUX].size);
> create_unimplemented_device("riscv.lowrisc.ibex.alert_handler",
>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v3 8/9] riscv/opentitan: Connect the UART device
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
` (6 preceding siblings ...)
2020-05-19 21:31 ` [PATCH v3 7/9] riscv/opentitan: Connect the PLIC device Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-20 6:03 ` Philippe Mathieu-Daudé
2020-05-19 21:31 ` [PATCH v3 9/9] target/riscv: Use a smaller guess size for no-MMU PMP Alistair Francis
8 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
---
include/hw/riscv/opentitan.h | 13 +++++++++++++
hw/riscv/opentitan.c | 24 ++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
index 8d6a09b696..825a3610bc 100644
--- a/include/hw/riscv/opentitan.h
+++ b/include/hw/riscv/opentitan.h
@@ -21,6 +21,7 @@
#include "hw/riscv/riscv_hart.h"
#include "hw/intc/ibex_plic.h"
+#include "hw/char/ibex_uart.h"
#define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
#define RISCV_IBEX_SOC(obj) \
@@ -33,6 +34,7 @@ typedef struct LowRISCIbexSoCState {
/*< public >*/
RISCVHartArrayState cpus;
IbexPlicState plic;
+ IbexUartState uart;
MemoryRegion flash_mem;
MemoryRegion rom;
@@ -63,4 +65,15 @@ enum {
IBEX_USBDEV,
};
+enum {
+ IBEX_UART_RX_PARITY_ERR_IRQ = 0x28,
+ IBEX_UART_RX_TIMEOUT_IRQ = 0x27,
+ IBEX_UART_RX_BREAK_ERR_IRQ = 0x26,
+ IBEX_UART_RX_FRAME_ERR_IRQ = 0x25,
+ IBEX_UART_RX_OVERFLOW_IRQ = 0x24,
+ IBEX_UART_TX_EMPTY_IRQ = 0x23,
+ IBEX_UART_RX_WATERMARK_IRQ = 0x22,
+ IBEX_UART_TX_WATERMARK_IRQ = 0x21
+};
+
#endif
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 3926321d8c..a6c0b949ca 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -96,6 +96,9 @@ static void riscv_lowrisc_ibex_soc_init(Object *obj)
sysbus_init_child_obj(obj, "plic", &s->plic,
sizeof(s->plic), TYPE_IBEX_PLIC);
+
+ sysbus_init_child_obj(obj, "uart", &s->uart,
+ sizeof(s->uart), TYPE_IBEX_UART);
}
static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
@@ -137,8 +140,25 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, memmap[IBEX_PLIC].base);
- create_unimplemented_device("riscv.lowrisc.ibex.uart",
- memmap[IBEX_UART].base, memmap[IBEX_UART].size);
+ /* UART */
+ dev = DEVICE(&(s->uart));
+ qdev_prop_set_chr(dev, "chardev", serial_hd(0));
+ object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, memmap[IBEX_UART].base);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(&s->plic),
+ IBEX_UART_TX_WATERMARK_IRQ));
+ sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(DEVICE(&s->plic),
+ IBEX_UART_RX_WATERMARK_IRQ));
+ sysbus_connect_irq(busdev, 2, qdev_get_gpio_in(DEVICE(&s->plic),
+ IBEX_UART_TX_EMPTY_IRQ));
+ sysbus_connect_irq(busdev, 3, qdev_get_gpio_in(DEVICE(&s->plic),
+ IBEX_UART_RX_OVERFLOW_IRQ));
+
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
memmap[IBEX_GPIO].base, memmap[IBEX_GPIO].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi",
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3 8/9] riscv/opentitan: Connect the UART device
2020-05-19 21:31 ` [PATCH v3 8/9] riscv/opentitan: Connect the UART device Alistair Francis
@ 2020-05-20 6:03 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-05-20 6:03 UTC (permalink / raw)
To: Alistair Francis, qemu-devel, qemu-riscv; +Cc: alistair23, bmeng.cn, palmer
On 5/19/20 11:31 PM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Bin Meng <bin.meng@windriver.com>
> ---
> include/hw/riscv/opentitan.h | 13 +++++++++++++
> hw/riscv/opentitan.c | 24 ++++++++++++++++++++++--
> 2 files changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
> index 8d6a09b696..825a3610bc 100644
> --- a/include/hw/riscv/opentitan.h
> +++ b/include/hw/riscv/opentitan.h
> @@ -21,6 +21,7 @@
>
> #include "hw/riscv/riscv_hart.h"
> #include "hw/intc/ibex_plic.h"
> +#include "hw/char/ibex_uart.h"
>
> #define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
> #define RISCV_IBEX_SOC(obj) \
> @@ -33,6 +34,7 @@ typedef struct LowRISCIbexSoCState {
> /*< public >*/
> RISCVHartArrayState cpus;
> IbexPlicState plic;
> + IbexUartState uart;
>
> MemoryRegion flash_mem;
> MemoryRegion rom;
> @@ -63,4 +65,15 @@ enum {
> IBEX_USBDEV,
> };
>
> +enum {
> + IBEX_UART_RX_PARITY_ERR_IRQ = 0x28,
> + IBEX_UART_RX_TIMEOUT_IRQ = 0x27,
> + IBEX_UART_RX_BREAK_ERR_IRQ = 0x26,
> + IBEX_UART_RX_FRAME_ERR_IRQ = 0x25,
> + IBEX_UART_RX_OVERFLOW_IRQ = 0x24,
> + IBEX_UART_TX_EMPTY_IRQ = 0x23,
> + IBEX_UART_RX_WATERMARK_IRQ = 0x22,
> + IBEX_UART_TX_WATERMARK_IRQ = 0x21
> +};
> +
> #endif
> diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
> index 3926321d8c..a6c0b949ca 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -96,6 +96,9 @@ static void riscv_lowrisc_ibex_soc_init(Object *obj)
>
> sysbus_init_child_obj(obj, "plic", &s->plic,
> sizeof(s->plic), TYPE_IBEX_PLIC);
> +
> + sysbus_init_child_obj(obj, "uart", &s->uart,
> + sizeof(s->uart), TYPE_IBEX_UART);
> }
>
> static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
> @@ -137,8 +140,25 @@ static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
> busdev = SYS_BUS_DEVICE(dev);
> sysbus_mmio_map(busdev, 0, memmap[IBEX_PLIC].base);
>
> - create_unimplemented_device("riscv.lowrisc.ibex.uart",
> - memmap[IBEX_UART].base, memmap[IBEX_UART].size);
> + /* UART */
> + dev = DEVICE(&(s->uart));
> + qdev_prop_set_chr(dev, "chardev", serial_hd(0));
> + object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
> + if (err != NULL) {
> + error_propagate(errp, err);
> + return;
> + }
> + busdev = SYS_BUS_DEVICE(dev);
> + sysbus_mmio_map(busdev, 0, memmap[IBEX_UART].base);
> + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(&s->plic),
> + IBEX_UART_TX_WATERMARK_IRQ));
> + sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(DEVICE(&s->plic),
> + IBEX_UART_RX_WATERMARK_IRQ));
> + sysbus_connect_irq(busdev, 2, qdev_get_gpio_in(DEVICE(&s->plic),
> + IBEX_UART_TX_EMPTY_IRQ));
> + sysbus_connect_irq(busdev, 3, qdev_get_gpio_in(DEVICE(&s->plic),
> + IBEX_UART_RX_OVERFLOW_IRQ));
> +
> create_unimplemented_device("riscv.lowrisc.ibex.gpio",
> memmap[IBEX_GPIO].base, memmap[IBEX_GPIO].size);
> create_unimplemented_device("riscv.lowrisc.ibex.spi",
>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v3 9/9] target/riscv: Use a smaller guess size for no-MMU PMP
2020-05-19 21:31 [PATCH v3 0/9] RISC-V Add the OpenTitan Machine Alistair Francis
` (7 preceding siblings ...)
2020-05-19 21:31 ` [PATCH v3 8/9] riscv/opentitan: Connect the UART device Alistair Francis
@ 2020-05-19 21:31 ` Alistair Francis
2020-05-21 1:52 ` Bin Meng
8 siblings, 1 reply; 21+ messages in thread
From: Alistair Francis @ 2020-05-19 21:31 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: alistair.francis, philmd, bmeng.cn, palmer, alistair23
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
target/riscv/pmp.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 0e6b640fbd..607a991260 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -233,12 +233,16 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
return true;
}
- /*
- * if size is unknown (0), assume that all bytes
- * from addr to the end of the page will be accessed.
- */
if (size == 0) {
- pmp_size = -(addr | TARGET_PAGE_MASK);
+ if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
+ /*
+ * If size is unknown (0), assume that all bytes
+ * from addr to the end of the page will be accessed.
+ */
+ pmp_size = -(addr | TARGET_PAGE_MASK);
+ } else {
+ pmp_size = sizeof(target_ulong);
+ }
} else {
pmp_size = size;
}
--
2.26.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3 9/9] target/riscv: Use a smaller guess size for no-MMU PMP
2020-05-19 21:31 ` [PATCH v3 9/9] target/riscv: Use a smaller guess size for no-MMU PMP Alistair Francis
@ 2020-05-21 1:52 ` Bin Meng
2020-05-27 0:51 ` Alistair Francis
0 siblings, 1 reply; 21+ messages in thread
From: Bin Meng @ 2020-05-21 1:52 UTC (permalink / raw)
To: Alistair Francis
Cc: Palmer Dabbelt, Philippe Mathieu-Daudé,
open list:RISC-V, qemu-devel@nongnu.org Developers,
Alistair Francis
On Wed, May 20, 2020 at 5:40 AM Alistair Francis
<alistair.francis@wdc.com> wrote:
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
> target/riscv/pmp.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
> index 0e6b640fbd..607a991260 100644
> --- a/target/riscv/pmp.c
> +++ b/target/riscv/pmp.c
> @@ -233,12 +233,16 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
> return true;
> }
>
> - /*
> - * if size is unknown (0), assume that all bytes
> - * from addr to the end of the page will be accessed.
> - */
> if (size == 0) {
> - pmp_size = -(addr | TARGET_PAGE_MASK);
> + if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
My previous comments were not fully addressed. I think the logic should be:
if (riscv_feature(env, RISCV_FEATURE_MMU))
Otherwise it does not match your comment and the commit title.
> + /*
> + * If size is unknown (0), assume that all bytes
> + * from addr to the end of the page will be accessed.
> + */
> + pmp_size = -(addr | TARGET_PAGE_MASK);
> + } else {
> + pmp_size = sizeof(target_ulong);
> + }
> } else {
> pmp_size = size;
> }
Regards,
Bin
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v3 9/9] target/riscv: Use a smaller guess size for no-MMU PMP
2020-05-21 1:52 ` Bin Meng
@ 2020-05-27 0:51 ` Alistair Francis
0 siblings, 0 replies; 21+ messages in thread
From: Alistair Francis @ 2020-05-27 0:51 UTC (permalink / raw)
To: Bin Meng
Cc: open list:RISC-V, Palmer Dabbelt, Alistair Francis,
qemu-devel@nongnu.org Developers, Philippe Mathieu-Daudé
On Wed, May 20, 2020 at 6:52 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Wed, May 20, 2020 at 5:40 AM Alistair Francis
> <alistair.francis@wdc.com> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > ---
> > target/riscv/pmp.c | 14 +++++++++-----
> > 1 file changed, 9 insertions(+), 5 deletions(-)
> >
> > diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
> > index 0e6b640fbd..607a991260 100644
> > --- a/target/riscv/pmp.c
> > +++ b/target/riscv/pmp.c
> > @@ -233,12 +233,16 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
> > return true;
> > }
> >
> > - /*
> > - * if size is unknown (0), assume that all bytes
> > - * from addr to the end of the page will be accessed.
> > - */
> > if (size == 0) {
> > - pmp_size = -(addr | TARGET_PAGE_MASK);
> > + if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
>
> My previous comments were not fully addressed. I think the logic should be:
>
> if (riscv_feature(env, RISCV_FEATURE_MMU))
>
> Otherwise it does not match your comment and the commit title.
Ah! You are right. This uncovered a bug with how we set the MMU as
well. I have fixed this and added a new patch.
Alistair
>
> > + /*
> > + * If size is unknown (0), assume that all bytes
> > + * from addr to the end of the page will be accessed.
> > + */
> > + pmp_size = -(addr | TARGET_PAGE_MASK);
> > + } else {
> > + pmp_size = sizeof(target_ulong);
> > + }
> > } else {
> > pmp_size = size;
> > }
>
> Regards,
> Bin
^ permalink raw reply [flat|nested] 21+ messages in thread