Re: [PATCH] target/avr: Ignore unimplemented WDR opcode

2021-05-05 Thread Fred Konrad




Le 5/2/21 à 9:09 PM, Philippe Mathieu-Daudé a écrit :

Running the WDR opcode triggers a segfault:

   $ cat > foo.S << EOF
   > __start:
   > wdr
   > EOF
   $ avr-gcc -nostdlib -nostartfiles -mmcu=avr6 foo.S -o foo.elf
   $ qemu-system-avr -serial mon:stdio -nographic -no-reboot \
 -M mega -bios foo.elf -d in_asm --singlestep
   IN:
   0x:  WDR
   Segmentation fault (core dumped)

   (gdb) bt
  #0  0xadd0b23a in gdb_get_cpu_pid (cpu=0xaf5a4af0) at 
../gdbstub.c:718
  #1  0xadd0b2dd in gdb_get_cpu_process (cpu=0xaf5a4af0) at 
../gdbstub.c:743
  #2  0xadd0e477 in gdb_set_stop_cpu (cpu=0xaf5a4af0) at 
../gdbstub.c:2742
  #3  0xadc99b96 in cpu_handle_guest_debug (cpu=0xaf5a4af0) at 
../softmmu/cpus.c:306
  #4  0xadcc66ab in rr_cpu_thread_fn (arg=0xaf5a4af0) at 
../accel/tcg/tcg-accel-ops-rr.c:224
  #5  0xadefaf12 in qemu_thread_start (args=0xaf5d9870) at 
../util/qemu-thread-posix.c:521
  #6  0x7f692d940ea5 in start_thread () from /lib64/libpthread.so.0
  #7  0x7f692d6699fd in clone () from /lib64/libc.so.6

Since the watchdog peripheral is not implemented, simply
log the opcode as unimplemented and keep going.

Reported-by: Fred Konrad 
Signed-off-by: Philippe Mathieu-Daudé 
---
  target/avr/helper.c | 6 +-
  1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/target/avr/helper.c b/target/avr/helper.c
index 35e10195940..981c29da453 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -188,11 +188,7 @@ void helper_break(CPUAVRState *env)
  
  void helper_wdr(CPUAVRState *env)

  {
-CPUState *cs = env_cpu(env);
-
-/* WD is not implemented yet, placeholder */
-cs->exception_index = EXCP_DEBUG;
-cpu_loop_exit(cs);
+qemu_log_mask(LOG_UNIMP, "WDG reset (not implemented)\n");
  }


Seems ok to me, at least better than having a segfault.

Reviewed-by: KONRAD Frederic 

  
  /*






Re: [PATCH] hw/avr/atmega.c: use the avr51 cpu for atmega1280

2021-05-05 Thread Fred Konrad




Le 4/30/21 à 12:27 PM, Joaquin de Andres a écrit :

On 4/28/21 9:17 PM, Philippe Mathieu-Daudé wrote:

Cc'ing Joaquín.

On 4/28/21 9:15 PM, Frederic Konrad wrote:

According to the as documentation:
  (https://sourceware.org/binutils/docs-2.36/as/AVR-Options.html)

"Instruction set avr51 is for the enhanced AVR core with exactly 128K
  program memory space (MCU types: atmega128, atmega128a, atmega1280,
  atmega1281, atmega1284, atmega1284p, atmega128rfa1, atmega128rfr2,
  atmega1284rfr2, at90can128, at90usb1286, at90usb1287, m3000)."

But when compiling a program for atmega1280 or avr51 and trying to execute
it:

$ cat > test.S << EOF

loop:
 rjmp loop
EOF

$ avr-gcc -nostdlib -nostartfiles -mmcu=atmega1280 test.S -o test.elf
$ qemu-system-avr -serial mon:stdio -nographic -no-reboot -M mega \
   -bios test.elf
qemu-system-avr: Current machine: Arduino Mega (ATmega1280) with 'avr6' CPU
qemu-system-avr: ELF image 'test.elf' is for 'avr51' CPU

So this fixes the atmega1280 class to use an avr51 CPU.

Signed-off-by: Frederic Konrad 
---
  hw/avr/atmega.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
index 44c6afebbb..e3ea5702f5 100644
--- a/hw/avr/atmega.c
+++ b/hw/avr/atmega.c
@@ -402,7 +402,7 @@ static void atmega1280_class_init(ObjectClass *oc, void 
*data)
  {
  AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
  
-amc->cpu_type = AVR_CPU_TYPE_NAME("avr6");

+amc->cpu_type = AVR_CPU_TYPE_NAME("avr51");
  amc->flash_size = 128 * KiB;
  amc->eeprom_size = 4 * KiB;
  amc->sram_size = 8 * KiB;




Good catch!



Thanks, does that count as a reviewed-by :)?




Re: [RFC 1/1] Implement AVR watchdog timer

2021-05-03 Thread Fred Konrad




Le 5/2/21 à 10:10 PM, Michael Rolnik a écrit :

Signed-off-by: Michael Rolnik 
---
  hw/avr/Kconfig|   1 +
  hw/avr/atmega.c   |  15 ++-
  hw/avr/atmega.h   |   2 +
  hw/watchdog/Kconfig   |   3 +
  hw/watchdog/avr_wdt.c | 190 ++
  hw/watchdog/meson.build   |   2 +
  hw/watchdog/trace-events  |   5 +
  include/hw/watchdog/avr_wdt.h |  47 +
  target/avr/cpu.c  |   3 +
  target/avr/cpu.h  |   1 +
  target/avr/helper.c   |   7 +-
  11 files changed, 271 insertions(+), 5 deletions(-)
  create mode 100644 hw/watchdog/avr_wdt.c
  create mode 100644 include/hw/watchdog/avr_wdt.h

diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
index d31298c3cc..9939e4902f 100644
--- a/hw/avr/Kconfig
+++ b/hw/avr/Kconfig
@@ -3,6 +3,7 @@ config AVR_ATMEGA_MCU
  select AVR_TIMER16
  select AVR_USART
  select AVR_POWER
+select AVR_WDT
  
  config ARDUINO

  select AVR_ATMEGA_MCU
diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
index 44c6afebbb..31ceb1c21c 100644
--- a/hw/avr/atmega.c
+++ b/hw/avr/atmega.c
@@ -28,6 +28,7 @@ enum AtmegaPeripheral {
  GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL,
  USART0, USART1, USART2, USART3,
  TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5,
+WDT,
  PERIFMAX
  };
  
@@ -75,6 +76,7 @@ static const peripheral_cfg dev168_328[PERIFMAX] = {

  [GPIOD] = {  0x29 },
  [GPIOC] = {  0x26 },
  [GPIOB] = {  0x23 },
+[WDT]   = {  0x60 },
  }, dev1280_2560[PERIFMAX] = {
  [USART3]= { 0x130, POWER1, 2 },
  [TIMER5]= { 0x120, POWER1, 5, 0x73, 0x3a, true },
@@ -99,6 +101,7 @@ static const peripheral_cfg dev168_328[PERIFMAX] = {
  [GPIOC] = {  0x26 },
  [GPIOB] = {  0x23 },
  [GPIOA] = {  0x20 },
+[WDT]   = {  0x60 },
  };
  
  enum AtmegaIrq {

@@ -118,6 +121,7 @@ enum AtmegaIrq {
  TIMER4_COMPC_IRQ, TIMER4_OVF_IRQ,
  TIMER5_CAPT_IRQ, TIMER5_COMPA_IRQ, TIMER5_COMPB_IRQ,
  TIMER5_COMPC_IRQ, TIMER5_OVF_IRQ,
+WATCHDOG_TIMER_IRQ,
  IRQ_COUNT
  };
  
@@ -133,6 +137,7 @@ enum AtmegaIrq {

  #define TIMER_OVF_IRQ(n)(n * TIMER_IRQ_COUNT + TIMER0_OVF_IRQ)
  
  static const uint8_t irq168_328[IRQ_COUNT] = {

+[WATCHDOG_TIMER_IRQ]= 7,
  [TIMER2_COMPA_IRQ]  = 8,
  [TIMER2_COMPB_IRQ]  = 9,
  [TIMER2_OVF_IRQ]= 10,
@@ -147,6 +152,7 @@ static const uint8_t irq168_328[IRQ_COUNT] = {
  [USART0_DRE_IRQ]= 20,
  [USART0_TXC_IRQ]= 21,
  }, irq1280_2560[IRQ_COUNT] = {
+[WATCHDOG_TIMER_IRQ]= 13,
  [TIMER2_COMPA_IRQ]  = 14,
  [TIMER2_COMPB_IRQ]  = 15,
  [TIMER2_OVF_IRQ]= 16,
@@ -344,10 +350,17 @@ static void atmega_realize(DeviceState *dev, Error **errp)
  g_free(devname);
  }
  
+/* Watchdog Timer */

+object_initialize_child(OBJECT(dev), "wdt", &s->wdt, TYPE_AVR_WDT);
+sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0,
+OFFSET_DATA + mc->dev[WDT].addr);
+qdev_connect_gpio_out_named(cpudev, "wdr", 0,
+qdev_get_gpio_in_named(DEVICE(&s->wdt), "wdr", 0));
+
  create_unimplemented_device("avr-twi",  OFFSET_DATA + 0x0b8, 6);
  create_unimplemented_device("avr-adc",  OFFSET_DATA + 0x078, 8);
  create_unimplemented_device("avr-ext-mem-ctrl", OFFSET_DATA + 0x074, 2);
-create_unimplemented_device("avr-watchdog", OFFSET_DATA + 0x060, 1);
  create_unimplemented_device("avr-spi",  OFFSET_DATA + 0x04c, 3);
  create_unimplemented_device("avr-eeprom",   OFFSET_DATA + 0x03f, 3);
  }
diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h
index a99ee15c7e..60bbd44bdd 100644
--- a/hw/avr/atmega.h
+++ b/hw/avr/atmega.h
@@ -13,6 +13,7 @@
  
  #include "hw/char/avr_usart.h"

  #include "hw/timer/avr_timer16.h"
+#include "hw/watchdog/avr_wdt.h"
  #include "hw/misc/avr_power.h"
  #include "target/avr/cpu.h"
  #include "qom/object.h"
@@ -45,6 +46,7 @@ struct AtmegaMcuState {
  AVRMaskState pwr[POWER_MAX];
  AVRUsartState usart[USART_MAX];
  AVRTimer16State timer[TIMER_MAX];
+AVRWatchdogState wdt;
  uint64_t xtal_freq_hz;
  };
  
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig

index 66e1d029e3..e0f89d2fe0 100644
--- a/hw/watchdog/Kconfig
+++ b/hw/watchdog/Kconfig
@@ -20,3 +20,6 @@ config WDT_IMX2
  
  config WDT_SBSA

  bool
+
+config AVR_WDT
+bool
diff --git a/hw/watchdog/avr_wdt.c b/hw/watchdog/avr_wdt.c
new file mode 100644
index 00..4ce1029a64
--- /dev/null
+++ b/hw/watchdog/avr_wdt.c
@@ -0,0 +1,190 @@
+/*
+ * AVR watchdog
+ *
+ * Copyright (c) 2018 Michael Rolnik


2021?


+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free

Re: [RFC 0/1] Implement AVR WDT (watchdog timer)

2021-05-03 Thread Fred Konrad

Hi Michael,

Le 5/2/21 à 10:10 PM, Michael Rolnik a écrit :

1.  Initial implementation of AVR WDT


Nice!


 There are two issues with this implementation so I need your help here
 a. when I configure the WDT to fire an interrupt every 15ms it actually 
happens every 6 instructions


Tested with the maximal prescaler: I've ~8 seconds which seems expected
according to the documentation, I don't know how much time it takes to run
through all the timers and go back in the execution loop, maybe 15ms is just too
low?


 b. when I specify --icount shift=0 qemu stucks


For me it just crashes:
  qemu-system-avr: Bad icount read

(gdb) bt
#0  icount_get_raw_locked () at ../src/softmmu/icount.c:117
#1  0x004e1801 in icount_get_locked () at ../src/softmmu/icount.c:128
#2  0x004e187a in icount_get () at ../src/softmmu/icount.c:154
#3  0x004bc8ff in cpus_get_virtual_clock () at ../src/softmmu/cpus.c:217
#4  0x006f5bd5 in qemu_clock_get_ns (type=QEMU_CLOCK_VIRTUAL) at 
../src/util/qemu-timer.c:637
#5  0x005422d7 in avr_wdt_reset_alarm (wdt=0xe14040) at 
../src/hw/watchdog/avr_wdt.c:74
#6  0x00542536 in avr_wdt_write (opaque=0xe14040, offset=0, val64=57, 
size=1) at ../src/hw/watchdog/avr_wdt.c:134
#7  0x004cdeaa in memory_region_write_accessor (mr=0xe14360, addr=0, 
value=0x7fff76ae9378, size=1, shift=0, mask=255, attrs=...) at 
../src/softmmu/memory.c:491
#8  0x004ce0cd in access_with_adjusted_size (addr=0, 
value=0x7fff76ae9378, size=1, access_size_min=1, access_size_max=1,
access_fn=0x4cddc7 , mr=0xe14360, attrs=...) 
at ../src/softmmu/memory.c:552



if (cpu && cpu->running) {
if (!cpu->can_do_io) {
error_report("Bad icount read");
exit(1);
HERE.
}

I'm not sure icount is supported on avr?  ie: I don't see any gen_io_start();
in target/avr?



Michael Rolnik (1):
   Implement AVR watchdog timer

  hw/avr/Kconfig|   1 +
  hw/avr/atmega.c   |  15 ++-
  hw/avr/atmega.h   |   2 +
  hw/watchdog/Kconfig   |   3 +
  hw/watchdog/avr_wdt.c | 188 ++
  hw/watchdog/meson.build   |   2 +
  hw/watchdog/trace-events  |   5 +
  include/hw/watchdog/avr_wdt.h |  47 +
  target/avr/cpu.c  |   3 +
  target/avr/cpu.h  |   1 +
  target/avr/helper.c   |   7 +-
  11 files changed, 269 insertions(+), 5 deletions(-)
  create mode 100644 hw/watchdog/avr_wdt.c
  create mode 100644 include/hw/watchdog/avr_wdt.h





Re: [RFC] AVR watchdog

2021-04-28 Thread Fred Konrad



Le 4/28/21 à 8:17 PM, Michael Rolnik a écrit :

Hi Fred.

How can I reproduce it?
Thank you.
Michael Rolnik



Hi Michael,

First sorry for the patchew noise, I didn't meant to sent a patch just an
inlined diff.

For the reproducer, that's pretty straight-forward with v6.0.0-rc5:

$ cat > foo.S << EOF
> __start:
> wdr
> EOF

$ avr-gcc -nostdlib -nostartfiles -mmcu=avr6 foo.S -o foo.elf
$ xxx/qemu-system-avr -serial mon:stdio -nographic -no-reboot -M mega \
  -bios foo.elf -d in_asm --singlestep
IN:
0x:  WDR

Segmentation fault (core dumped)

Note that I put "--singlestep" here to avoid translating NOPs after the WDR,
it breaks without as well.

Fred



Re: [PATCH v2 3/4] hw/sparc64: Fix code style for checkpatch.pl

2021-04-28 Thread Fred Konrad




Le 4/28/21 à 4:16 PM, Philippe Mathieu-Daudé a écrit :

We are going to move this code, fix its style first.

Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: KONRAD Frederic 


---
  hw/sparc64/sparc64.c | 12 
  1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index cc0b9bd30d3..fd29a79edc0 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -48,14 +48,18 @@ void cpu_check_irqs(CPUSPARCState *env)
  return;
  }
  cs = env_cpu(env);
-/* check if TM or SM in SOFTINT are set
-   setting these also causes interrupt 14 */
+/*
+ * check if TM or SM in SOFTINT are set
+ * setting these also causes interrupt 14
+ */
  if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
  pil |= 1 << 14;
  }
  
-/* The bit corresponding to psrpil is (1<< psrpil), the next bit

-   is (2 << psrpil). */
+/*
+ * The bit corresponding to psrpil is (1<< psrpil),
+ * the next bit is (2 << psrpil).
+ */
  if (pil < (2 << env->psrpil)) {
  if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
  trace_sparc64_cpu_check_irqs_reset_irq(env->interrupt_index);





Re: [PATCH v2 2/4] hw/sparc64: Remove unused "hw/char/serial.h" header

2021-04-28 Thread Fred Konrad




Le 4/28/21 à 4:16 PM, Philippe Mathieu-Daudé a écrit :

Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: KONRAD Frederic 


---
  hw/sparc64/sparc64.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index e3f9219a101..cc0b9bd30d3 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -26,7 +26,6 @@
  #include "qemu/osdep.h"
  #include "cpu.h"
  #include "hw/boards.h"
-#include "hw/char/serial.h"
  #include "hw/sparc/sparc64.h"
  #include "qemu/timer.h"
  #include "sysemu/reset.h"





[RFC] AVR watchdog

2021-04-28 Thread Fred Konrad

Hi,

I fall on a segfault while running the wdr instruction on AVR:

(gdb) bt
 #0  0xadd0b23a in gdb_get_cpu_pid (cpu=0xaf5a4af0) at
   ../gdbstub.c:718
 #1  0xadd0b2dd in gdb_get_cpu_process (cpu=0xaf5a4af0) at
   ../gdbstub.c:743
 #2  0xadd0e477 in gdb_set_stop_cpu (cpu=0xaf5a4af0) at
   ../gdbstub.c:2742
 #3  0xadc99b96 in cpu_handle_guest_debug (cpu=0xaf5a4af0) at
   ../softmmu/cpus.c:306
 #4  0xadcc66ab in rr_cpu_thread_fn (arg=0xaf5a4af0) at
   ../accel/tcg/tcg-accel-ops-rr.c:224
 #5  0xadefaf12 in qemu_thread_start (args=0xaf5d9870) at
   ../util/qemu-thread-posix.c:521
 #6  0x7f692d940ea5 in start_thread () from /lib64/libpthread.so.0
 #7  0x7f692d6699fd in clone () from /lib64/libc.so.6

Wondering if there are some plan/on-going work to implement this watchdog?

---

Also meanwhile I though about a workaround like that:

diff --git a/target/avr/helper.c b/target/avr/helper.c
index 35e1019594..7944ed21f4 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "exec/address-spaces.h"
 #include "exec/helper-proto.h"
+#include "sysemu/runstate.h"

 bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
@@ -191,7 +192,7 @@ void helper_wdr(CPUAVRState *env)
 CPUState *cs = env_cpu(env);

 /* WD is not implemented yet, placeholder */
-cs->exception_index = EXCP_DEBUG;
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 cpu_loop_exit(cs);
 }

In the case the guest wants to reset the board through the watchdog, would that
make sense to swap to that?

Best Regards,
Fred



Re: [RFC PATCH 2/2] hw/sparc: Allow building without the leon3 machine

2021-04-28 Thread Fred Konrad

Hi Philippe,

Le 4/27/21 à 9:26 PM, Philippe Mathieu-Daudé a écrit :

When building without the leon3 machine, we get this link failure:

   /usr/bin/ld: target_sparc_int32_helper.c.o: in function `leon3_irq_manager':
   target/sparc/int32_helper.c:172: undefined reference to `leon3_irq_ack'

This is because the leon3_irq_ack() is declared in hw/sparc/leon3.c,
which is only build when CONFIG_LEON3 is selected.

Fix by moving the leon3_cache_control_int() / leon3_irq_manager()
(which are specific to the leon3 machine) to hw/sparc/leon3.c.
Move the trace events along (but don't rename them).

leon3_irq_ack() is now locally used, declare it static to reduce
its scope.

Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: KONRAD Frederic 
Tested-by: KONRAD Frederic 

Thanks for the fix!


---
RFC: The problem is we have hardware specific code in the
architectural translation code. I wish there was a better
alternative rather than moving this code to hw/sparc/.
---
  target/sparc/cpu.h  |  6 --
  hw/sparc/leon3.c| 37 -
  target/sparc/int32_helper.c | 37 -
  hw/sparc/trace-events   |  2 ++
  target/sparc/trace-events   |  4 
  5 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 4b2290650be..ff8ae73002a 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -615,15 +615,9 @@ int cpu_cwp_inc(CPUSPARCState *env1, int cwp);
  int cpu_cwp_dec(CPUSPARCState *env1, int cwp);
  void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
  
-/* int_helper.c */

-void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno);
-
  /* sun4m.c, sun4u.c */
  void cpu_check_irqs(CPUSPARCState *env);
  
-/* leon3.c */

-void leon3_irq_ack(void *irq_manager, int intno);
-
  #if defined (TARGET_SPARC64)
  
  static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)

diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 7e16eea9e67..98e3789cf84 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -137,7 +137,36 @@ static void main_cpu_reset(void *opaque)
  env->regbase[6] = s->sp;
  }
  
-void leon3_irq_ack(void *irq_manager, int intno)

+static void leon3_cache_control_int(CPUSPARCState *env)
+{
+uint32_t state = 0;
+
+if (env->cache_control & CACHE_CTRL_IF) {
+/* Instruction cache state */
+state = env->cache_control & CACHE_STATE_MASK;
+if (state == CACHE_ENABLED) {
+state = CACHE_FROZEN;
+trace_int_helper_icache_freeze();
+}
+
+env->cache_control &= ~CACHE_STATE_MASK;
+env->cache_control |= state;
+}
+
+if (env->cache_control & CACHE_CTRL_DF) {
+/* Data cache state */
+state = (env->cache_control >> 2) & CACHE_STATE_MASK;
+if (state == CACHE_ENABLED) {
+state = CACHE_FROZEN;
+trace_int_helper_dcache_freeze();
+}
+
+env->cache_control &= ~(CACHE_STATE_MASK << 2);
+env->cache_control |= (state << 2);
+}
+}
+
+static void leon3_irq_ack(void *irq_manager, int intno)
  {
  grlib_irqmp_ack((DeviceState *)irq_manager, intno);
  }
@@ -181,6 +210,12 @@ static void leon3_set_pil_in(void *opaque, int n, int 
level)
  }
  }
  
+static void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno)

+{
+leon3_irq_ack(irq_manager, intno);
+leon3_cache_control_int(env);
+}
+
  static void leon3_generic_hw_init(MachineState *machine)
  {
  ram_addr_t ram_size = machine->ram_size;
diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
index 817a463a179..d008dbdb65c 100644
--- a/target/sparc/int32_helper.c
+++ b/target/sparc/int32_helper.c
@@ -136,40 +136,3 @@ void sparc_cpu_do_interrupt(CPUState *cs)
  }
  #endif
  }
-
-#if !defined(CONFIG_USER_ONLY)
-static void leon3_cache_control_int(CPUSPARCState *env)
-{
-uint32_t state = 0;
-
-if (env->cache_control & CACHE_CTRL_IF) {
-/* Instruction cache state */
-state = env->cache_control & CACHE_STATE_MASK;
-if (state == CACHE_ENABLED) {
-state = CACHE_FROZEN;
-trace_int_helper_icache_freeze();
-}
-
-env->cache_control &= ~CACHE_STATE_MASK;
-env->cache_control |= state;
-}
-
-if (env->cache_control & CACHE_CTRL_DF) {
-/* Data cache state */
-state = (env->cache_control >> 2) & CACHE_STATE_MASK;
-if (state == CACHE_ENABLED) {
-state = CACHE_FROZEN;
-trace_int_helper_dcache_freeze();
-}
-
-env->cache_control &= ~(CACHE_STATE_MASK << 2);
-env->cache_control |= (state << 2);
-}
-}
-
-void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno)
-{
-leon3_irq_ack(irq_manager, intno);
-leon3_cache_control_int(env);
-}
-#endif
diff --git a/hw/sparc/trace-events b/hw/sparc/trace-events
index 355b07ae057..dfb53dc1a24 100644
--- a

Re: [PATCH 0/2] hw/sparc: Kconfig fixes to build with/without the leon3 machine

2021-04-28 Thread Fred Konrad




Le 4/27/21 à 9:26 PM, Philippe Mathieu-Daudé a écrit :

This series fixes link failure when building either the leon3
machine or the sun4m ones.

The problem is we have hardware specific code in the architectural
translation code. Move this code to hw/sparc/.

The link failures can be reproduced doing:

   $ echo CONFIG_LEON3=y > default-configs/devices/sparc-softmmu.mak
   $ configure --without-default-devices
   $ ninja qemu-system-sparc


Indeed:

libqemu-sparc-softmmu.fa.p/target_sparc_win_helper.c.o: \
In function `cpu_put_psr':
xxx/qemu/build/../target/sparc/win_helper.c:91: \
  undefined reference to `cpu_check_irqs'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.


   $ ./qemu-system-sparc -M leon3 -S

or:

   $ echo CONFIG_SUN4M=y > default-configs/devices/sparc-softmmu.mak

Philippe Mathieu-Daudé (2):
   hw/sparc: Allow building the leon3 machine stand-alone
   hw/sparc: Allow building without the leon3 machine

  target/sparc/cpu.h  |  6 
  hw/sparc/irq.c  | 61 +
  hw/sparc/leon3.c| 37 +-
  hw/sparc/sun4m.c| 32 ---
  target/sparc/int32_helper.c | 37 --
  hw/sparc/meson.build|  1 +
  hw/sparc/trace-events   |  2 ++
  target/sparc/trace-events   |  4 ---
  8 files changed, 100 insertions(+), 80 deletions(-)
  create mode 100644 hw/sparc/irq.c





Re: [PATCH 0/2] sparc/leon3: Make grlib-irqmp handle its own inbound IRQ lines

2021-01-05 Thread Fred Konrad




Le 12/12/20 à 3:41 PM, Peter Maydell a écrit :

Currently the GRLIB_IRQMP device is used in one place (the leon3
board), but instead of the device providing inbound gpio lines for
the board to wire up, the board code itself calls
qemu_allocate_irqs() with the handler function being a set_irq
function defined in the code for the device.

Patch one in this series refactors this into the standard setup of a
device having input gpio lines.  The main motivation here is that it
squashes a trivial Coverity memory leak warning.  Patch two just
removes a stray unused typedef that I noticed in passing.

Incidentally I suspect the irqmp_ack logic could also be done more
neatly, but I didn't feel like getting into that at this point.


Indeed, and I've some cleanup patches for that, but never had time to submit
them.  Hopefully sometime in 2021 :).

Cheers,
Fred



Tested by booting the 'buildroot' image downloadable from
https://www.gaisler.com/anonftp/linux/linux-2.6/images/leon-linux-4.9/leon-linux-4.9-1.0/up/
and runnable with
  ./build/sparc-all/qemu-system-sparc -M leon3_generic -display none -serial 
stdio -kernel image.ram


thanks
-- PMM

Peter Maydell (2):
   hw/sparc: Make grlib-irqmp device handle its own inbound IRQ lines
   include/hw/sparc/grlib.h: Remove unused set_pil_in_fn typedef

  include/hw/sparc/grlib.h |  4 
  hw/intc/grlib_irqmp.c|  5 -
  hw/sparc/leon3.c | 21 +
  3 files changed, 13 insertions(+), 17 deletions(-)





Re: [PATCH 2/2] include/hw/sparc/grlib.h: Remove unused set_pil_in_fn typedef

2021-01-05 Thread Fred Konrad




Le 12/12/20 à 3:41 PM, Peter Maydell a écrit :

The grlib.h header defines a set_pil_in_fn typedef which is never
used; remove it.

Signed-off-by: Peter Maydell 
---
  include/hw/sparc/grlib.h | 2 --
  1 file changed, 2 deletions(-)

diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h
index e1d1beaa73f..2104f493f32 100644
--- a/include/hw/sparc/grlib.h
+++ b/include/hw/sparc/grlib.h
@@ -34,8 +34,6 @@
  /* IRQMP */
  #define TYPE_GRLIB_IRQMP "grlib,irqmp"
  
-typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in);

-
  void grlib_irqmp_ack(DeviceState *dev, int intno);
  
  /* GPTimer */




Reviewed-by: KONRAD Frederic 



Re: [PATCH 1/2] hw/sparc: Make grlib-irqmp device handle its own inbound IRQ lines

2021-01-05 Thread Fred Konrad



Hi Peter,

Le 12/12/20 à 3:41 PM, Peter Maydell a écrit :

Currently the GRLIB_IRQMP device is used in one place (the leon3 board),
but instead of the device providing inbound gpio lines for the board
to wire up, the board code itself calls qemu_allocate_irqs() with
the handler function being a set_irq function defined in the code
for the device.

Refactor this into the standard setup of a device having input
gpio lines.

This fixes a trivial Coverity memory leak report (the leon3
board code leaks the IRQ array returned from qemu_allocate_irqs()).

Fixes: Coverity CID 1421922
Signed-off-by: Peter Maydell 
---
  include/hw/sparc/grlib.h |  2 --
  hw/intc/grlib_irqmp.c|  5 -
  hw/sparc/leon3.c | 21 +
  3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h
index 78b6178fcd8..e1d1beaa73f 100644
--- a/include/hw/sparc/grlib.h
+++ b/include/hw/sparc/grlib.h
@@ -36,8 +36,6 @@
  
  typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in);
  
-void grlib_irqmp_set_irq(void *opaque, int irq, int level);

-
  void grlib_irqmp_ack(DeviceState *dev, int intno);
  
  /* GPTimer */

diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index ffec4a07eec..984334fa7bf 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -51,6 +51,8 @@
  #define FORCE_OFFSET 0x80
  #define EXTENDED_OFFSET  0xC0
  
+#define MAX_PILS 16

+
  OBJECT_DECLARE_SIMPLE_TYPE(IRQMP, GRLIB_IRQMP)
  
  typedef struct IRQMPState IRQMPState;

@@ -126,7 +128,7 @@ void grlib_irqmp_ack(DeviceState *dev, int intno)
  grlib_irqmp_ack_mask(state, mask);
  }
  
-void grlib_irqmp_set_irq(void *opaque, int irq, int level)

+static void grlib_irqmp_set_irq(void *opaque, int irq, int level)
  {
  IRQMP  *irqmp = GRLIB_IRQMP(opaque);
  IRQMPState *s;
@@ -328,6 +330,7 @@ static void grlib_irqmp_init(Object *obj)
  IRQMP *irqmp = GRLIB_IRQMP(obj);
  SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  
+qdev_init_gpio_in(DEVICE(obj), grlib_irqmp_set_irq, MAX_PILS);

  qdev_init_gpio_out_named(DEVICE(obj), &irqmp->irq, "grlib-irq", 1);
  memory_region_init_io(&irqmp->iomem, obj, &grlib_irqmp_ops, irqmp,
"irqmp", IRQMP_REG_SIZE);
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 4bc4ebea841..7e16eea9e67 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -52,8 +52,6 @@
  #define LEON3_PROM_OFFSET(0x)
  #define LEON3_RAM_OFFSET (0x4000)
  
-#define MAX_PILS 16

-
  #define LEON3_UART_OFFSET  (0x8100)
  #define LEON3_UART_IRQ (3)
  
@@ -194,11 +192,10 @@ static void leon3_generic_hw_init(MachineState *machine)

  MemoryRegion *prom = g_new(MemoryRegion, 1);
  int ret;
  char   *filename;
-qemu_irq   *cpu_irqs = NULL;
  int bios_size;
  int prom_size;
  ResetData  *reset_info;
-DeviceState *dev;
+DeviceState *dev, *irqmpdev;
  int i;
  AHBPnp *ahb_pnp;
  APBPnp *apb_pnp;
@@ -230,16 +227,15 @@ static void leon3_generic_hw_init(MachineState *machine)
  GRLIB_AHB_SLAVE, GRLIB_AHBMEM_AREA);
  
  /* Allocate IRQ manager */

-dev = qdev_new(TYPE_GRLIB_IRQMP);
+irqmpdev = qdev_new(TYPE_GRLIB_IRQMP);
  qdev_init_gpio_in_named_with_opaque(DEVICE(cpu), leon3_set_pil_in,
  env, "pil", 1);
-qdev_connect_gpio_out_named(dev, "grlib-irq", 0,
+qdev_connect_gpio_out_named(irqmpdev, "grlib-irq", 0,
  qdev_get_gpio_in_named(DEVICE(cpu), "pil", 
0));
-sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
-sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_IRQMP_OFFSET);
-env->irq_manager = dev;
+sysbus_realize_and_unref(SYS_BUS_DEVICE(irqmpdev), &error_fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(irqmpdev), 0, LEON3_IRQMP_OFFSET);
+env->irq_manager = irqmpdev;
  env->qemu_irq_ack = leon3_irq_manager;
-cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq, dev, MAX_PILS);
  grlib_apb_pnp_add_entry(apb_pnp, LEON3_IRQMP_OFFSET, 0xFFF,
  GRLIB_VENDOR_GAISLER, GRLIB_IRQMP_DEV,
  2, 0, GRLIB_APBIO_AREA);
@@ -330,7 +326,7 @@ static void leon3_generic_hw_init(MachineState *machine)
  sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_TIMER_OFFSET);
  for (i = 0; i < LEON3_TIMER_COUNT; i++) {
  sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
-   cpu_irqs[LEON3_TIMER_IRQ + i]);
+   qdev_get_gpio_in(irqmpdev, LEON3_TIMER_IRQ + i));
  }
  
  grlib_apb_pnp_add_entry(apb_pnp, LEON3_TIMER_OFFSET, 0xFFF,

@@ -342,7 +338,8 @@ static void leon3_generic_hw_init(MachineState *machine)
  qdev_prop_set_chr(dev, "chrdev", serial_hd(0));
  sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_U

Re: [PATCH v1 1/2] semihosting: defer connect_chardevs a little more to use serialx

2020-07-15 Thread Fred Konrad




Le 6/26/20 à 12:06 PM, Fred Konrad a écrit :



Le 6/16/20 à 4:52 PM, Alex Bennée a écrit :


kon...@adacore.com writes:


From: KONRAD Frederic 

With that we can just use chardev=serial0.


I don't quite follow what this means.

./aarch64-softmmu/qemu-system-aarch64 -cpu max -monitor none -chardev=serial0 
-M virt -display none -semihosting -kernel ./tests/tcg/aarch64-softmmu/memory

qemu-system-aarch64: -chardev=serial0: invalid option

./aarch64-softmmu/qemu-system-aarch64 -cpu max -monitor none -chardev 
id=serial0 -M virt -display none -semihosting -kernel 
./tests/tcg/aarch64-softmmu/memory

qemu-system-aarch64: -chardev id=serial0: chardev: "serial0" missing backend

The run:

./aarch64-softmmu/qemu-system-aarch64 -cpu max -serial mon:stdio -M virt 
-display none -semihosting -kernel ./tests/tcg/aarch64-softmmu/memory


works fine without this patch.


Hi Alex, and sorry for the delay,

I meant `-semihosting-config chardev=serial0`.  I suspect your last command-line
will print any string sent to semihosting to stderr by default.


Does that make sense?  BTW the second patch fixes a bug, it might be interesting
to have it in 5.1.

Cheers,
Fred







Signed-off-by: KONRAD Frederic 
---
  softmmu/vl.c | 5 +++--
  1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index f669c06..9b8b48a 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4123,8 +4123,6 @@ void qemu_init(int argc, char **argv, char **envp)
  qemu_opts_foreach(qemu_find_opts("chardev"),
    chardev_init_func, NULL, &error_fatal);
-    /* now chardevs have been created we may have semihosting to connect */
-    qemu_semihosting_connect_chardevs();
  #ifdef CONFIG_VIRTFS
  qemu_opts_foreach(qemu_find_opts("fsdev"),
@@ -4271,6 +4269,9 @@ void qemu_init(int argc, char **argv, char **envp)
  if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
  exit(1);
+    /* now chardevs have been created we may have semihosting to connect */
+    qemu_semihosting_connect_chardevs();
+
  /* If no default VGA is requested, the default is "none".  */
  if (default_vga) {
  vga_model = get_default_vga_model(machine_class);







Re: [PATCH] i2c: Match parameters of i2c_start_transfer and i2c_send_recv

2020-06-26 Thread Fred Konrad



Hi Corey,

Le 6/22/20 à 11:32 PM, Corey Minyard a écrit :

On Sun, Jun 21, 2020 at 04:43:38PM +0200, BALATON Zoltan wrote:

These functions have a parameter that decides the direction of
transfer but totally confusingly they don't match but inverted sense.
To avoid frequent mistakes when using these functions change
i2c_send_recv to match i2c_start_transfer. Also use bool in
i2c_start_transfer instead of int to match i2c_send_recv.


Hmm, I have to admit that this is a little better.  Indeed the
hw/misc/auxbus.c looks suspicious.  I can't imagine that code has ever
been tested.


Sorry to hear that..., this auxbus stuff is related to the Xilinx Display Port
device, so you may want to CC the MAINTAINERS of the Xilinx Display Port.

Now about the testing, in theory this code is executed when the driver try to 
fetch the EDID from the i2c-ddc device which is connected to it, and you won't

get any framebuffer with an empty EDID.

But this was long ago and I don't have any image anymore to test that today.
CC'ed Edgar, he can probably help with that.

Regards,
Fred



I don't know the policy on changing an API like this with silent
semantic changes.  You've gotten all the internal ones; I'm wondering if
we worry about silently breaking out of tree things.

I'll pull this into my tree, but hopefully others will comment on this.

-corey



Signed-off-by: BALATON Zoltan 
---
Looks like hw/misc/auxbus.c already got this wrong and calls both
i2c_start_transfer and i2c_send_recv with same is_write parameter.
Although the name of the is_write variable suggest this may need to be
inverted I'm not sure what that value actially means and which usage
was correct so I did not touch it. Someone knowing this device might
want to review and fix it.

  hw/display/sm501.c   |  2 +-
  hw/i2c/core.c| 34 +-
  hw/i2c/ppc4xx_i2c.c  |  2 +-
  include/hw/i2c/i2c.h |  4 ++--
  4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index 2db347dcbc..ccd0a6e376 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1034,7 +1034,7 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, 
uint64_t value,
  int i;
  for (i = 0; i <= s->i2c_byte_count; i++) {
  res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i],
-!(s->i2c_addr & 1));
+s->i2c_addr & 1);
  if (res) {
  s->i2c_status |= SM501_I2C_STATUS_ERROR;
  return;
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 1aac457a2a..c9d01df427 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -91,7 +91,7 @@ int i2c_bus_busy(I2CBus *bus)
   * without releasing the bus.  If that fails, the bus is still
   * in a transaction.
   */
-int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
+int i2c_start_transfer(I2CBus *bus, uint8_t address, bool recv)
  {
  BusChild *kid;
  I2CSlaveClass *sc;
@@ -175,26 +175,14 @@ void i2c_end_transfer(I2CBus *bus)
  bus->broadcast = false;
  }
  
-int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)

+int i2c_send_recv(I2CBus *bus, uint8_t *data, bool recv)
  {
  I2CSlaveClass *sc;
  I2CSlave *s;
  I2CNode *node;
  int ret = 0;
  
-if (send) {

-QLIST_FOREACH(node, &bus->current_devs, next) {
-s = node->elt;
-sc = I2C_SLAVE_GET_CLASS(s);
-if (sc->send) {
-trace_i2c_send(s->address, *data);
-ret = ret || sc->send(s, *data);
-} else {
-ret = -1;
-}
-}
-return ret ? -1 : 0;
-} else {
+if (recv) {
  ret = 0xff;
  if (!QLIST_EMPTY(&bus->current_devs) && !bus->broadcast) {
  sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
@@ -206,19 +194,31 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
  }
  *data = ret;
  return 0;
+} else {
+QLIST_FOREACH(node, &bus->current_devs, next) {
+s = node->elt;
+sc = I2C_SLAVE_GET_CLASS(s);
+if (sc->send) {
+trace_i2c_send(s->address, *data);
+ret = ret || sc->send(s, *data);
+} else {
+ret = -1;
+}
+}
+return ret ? -1 : 0;
  }
  }
  
  int i2c_send(I2CBus *bus, uint8_t data)

  {
-return i2c_send_recv(bus, &data, true);
+return i2c_send_recv(bus, &data, false);
  }
  
  uint8_t i2c_recv(I2CBus *bus)

  {
  uint8_t data = 0xff;
  
-i2c_send_recv(bus, &data, false);

+i2c_send_recv(bus, &data, true);
  return data;
  }
  
diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c

index c0a8e04567..d3899203a4 100644
--- a/hw/i2c/ppc4xx_i2c.c
+++ b/hw/i2c/ppc4xx_i2c.c
@@ -239,7 +239,7 @@ static void ppc4x

Re: [PATCH v1 1/2] semihosting: defer connect_chardevs a little more to use serialx

2020-06-26 Thread Fred Konrad




Le 6/16/20 à 4:52 PM, Alex Bennée a écrit :


kon...@adacore.com writes:


From: KONRAD Frederic 

With that we can just use chardev=serial0.


I don't quite follow what this means.

./aarch64-softmmu/qemu-system-aarch64 -cpu max -monitor none -chardev=serial0 
-M virt -display none -semihosting -kernel ./tests/tcg/aarch64-softmmu/memory
qemu-system-aarch64: -chardev=serial0: invalid option

./aarch64-softmmu/qemu-system-aarch64 -cpu max -monitor none -chardev 
id=serial0 -M virt -display none -semihosting -kernel 
./tests/tcg/aarch64-softmmu/memory
qemu-system-aarch64: -chardev id=serial0: chardev: "serial0" missing backend

The run:

./aarch64-softmmu/qemu-system-aarch64 -cpu max -serial mon:stdio -M virt 
-display none -semihosting -kernel ./tests/tcg/aarch64-softmmu/memory

works fine without this patch.


Hi Alex, and sorry for the delay,

I meant `-semihosting-config chardev=serial0`.  I suspect your last command-line
will print any string sent to semihosting to stderr by default.





Signed-off-by: KONRAD Frederic 
---
  softmmu/vl.c | 5 +++--
  1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index f669c06..9b8b48a 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4123,8 +4123,6 @@ void qemu_init(int argc, char **argv, char **envp)
  
  qemu_opts_foreach(qemu_find_opts("chardev"),

chardev_init_func, NULL, &error_fatal);
-/* now chardevs have been created we may have semihosting to connect */
-qemu_semihosting_connect_chardevs();
  
  #ifdef CONFIG_VIRTFS

  qemu_opts_foreach(qemu_find_opts("fsdev"),
@@ -4271,6 +4269,9 @@ void qemu_init(int argc, char **argv, char **envp)
  if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
  exit(1);
  
+/* now chardevs have been created we may have semihosting to connect */

+qemu_semihosting_connect_chardevs();
+
  /* If no default VGA is requested, the default is "none".  */
  if (default_vga) {
  vga_model = get_default_vga_model(machine_class);







Re: [PATCH 1/2] softfloat: m68k: infinity is a valid encoding

2020-06-15 Thread Fred Konrad

Missed this one sorry.

Le 6/12/20 à 10:31 AM, Laurent Vivier a écrit :

Le 28/04/2020 à 19:17, KONRAD Frederic a écrit :

The MC68881 say about infinities (3.2.4):

"*For the extended precision format, the most significant bit of the
mantissa (the integer bit) is a don't care."

https://www.nxp.com/docs/en/reference-manual/MC68881UM.pdf

The m68k extended format is implemented with the floatx80 and
floatx80_invalid_encoding currently treats 0x7fff as
an invalid encoding.  This patch fixes floatx80_invalid_encoding so it
accepts that the most significant bit of the mantissa can be 0.

This bug can be revealed with the following code which pushes extended
infinity on the stack as a double and then reloads it as a double.  It
should normally be converted and read back as infinity and is currently
read back as nan:

 .global _start
 .text
_start:
 lea val, %a0
 lea fp, %fp
 fmovex (%a0), %fp0
 fmoved %fp0, %fp@(-8)
 fmoved %fp@(-8), %fp0
end:
 bra end

.align 0x4
val:
 .fill 1, 4, 0x7fff
 .fill 1, 4, 0x
 .fill 1, 4, 0x
.align 0x4
 .fill 0x100, 1, 0
fp:



[...]



According to "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL" the explicit
integer bit is "Don't care" for signed infinite (a.high == 0x7FFF) (this
is the case this patch manages).

But wit a zero exponent and a non zero mantissa, it's a denormal number,
and a signed zero has also a zero explicit integer bit but a zero
mantissa. (both cases are already managed in the existing code).

with a non zero exponent less than the maximum value it's an unnormal
number.

The denormal and unnormal numbers must be managed during the load
operation in the m68k TCG emulation to generate directly the FP_UNIMP
exception.


Is this already handled in the TCG code?

Thanks,
Fred



So I think, in the end, we don't have invalid number at softfloat level
and floatx80_invalid_encoding() should always return "false" for
TARGET_M68K.

Thanks,
Laurent





Re: [PATCH 1/3] hw/sparc/leon3: Map the UART device unconditionally

2020-06-08 Thread Fred Konrad




Le 6/8/20 à 7:21 PM, Philippe Mathieu-Daudé a écrit :

The UART is present on the chipset regardless there is a
character device connected to it. Map it unconditionally.

Signed-off-by: Philippe Mathieu-Daudé 
---
  hw/sparc/leon3.c | 18 --
  1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 8f024dab7b..cc55117dec 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -339,16 +339,14 @@ static void leon3_generic_hw_init(MachineState *machine)
  0, LEON3_TIMER_IRQ, GRLIB_APBIO_AREA);
  
  /* Allocate uart */

-if (serial_hd(0)) {
-dev = qdev_create(NULL, TYPE_GRLIB_APB_UART);
-qdev_prop_set_chr(dev, "chrdev", serial_hd(0));
-qdev_init_nofail(dev);
-sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET);
-sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]);
-grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF,
-GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1,
-LEON3_UART_IRQ, GRLIB_APBIO_AREA);
-}
+dev = qdev_create(NULL, TYPE_GRLIB_APB_UART);
+qdev_prop_set_chr(dev, "chrdev", serial_hd(0));
+qdev_init_nofail(dev);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET);
+sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]);
+grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF,
+GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1,
+LEON3_UART_IRQ, GRLIB_APBIO_AREA);
  }
  
  static void leon3_generic_machine_init(MachineClass *mc)




Reviewed-by: KONRAD Frederic 

Thanks!



Re: [PATCH] semihosting: remove the pthread include which seems unused

2020-06-01 Thread Fred Konrad




Le 5/18/20 à 3:50 PM, Philippe Mathieu-Daudé a écrit :

On 5/18/20 3:02 PM, kon...@adacore.com wrote:

From: KONRAD Frederic 

This have been introduced by:
   8de702cb677c8381fb702cae252d6b69aa4c653b

It doesn't seem to be used so remove it.

Signed-off-by: KONRAD Frederic 
---
  hw/semihosting/console.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c
index 6346bd7..22e7827 100644
--- a/hw/semihosting/console.c
+++ b/hw/semihosting/console.c
@@ -23,7 +23,6 @@
  #include "exec/exec-all.h"
  #include "qemu/log.h"
  #include "chardev/char.h"
-#include 
  #include "chardev/char-fe.h"
  #include "sysemu/sysemu.h"
  #include "qemu/main-loop.h"



Reviewed-by: Philippe Mathieu-Daudé 



Thanks for the review, Philippe.  Can this go through qemu-trivial?

Regards,
Fred



Re: [RFC] some semihosting interrogation

2020-05-29 Thread Fred Konrad




Le 5/28/20 à 2:00 PM, Philippe Mathieu-Daudé a écrit :

Hi Fred,

On 5/28/20 11:44 AM, Fred Konrad wrote:

Hi all,

Just wonderring if there is any reason not to be able to defer
qemu_semihosting_connect_chardevs a little more to be able to specify
chardev=serial0?

Like:

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 6390cf0..9fa1553 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4333,8 +4333,6 @@ void qemu_init(int argc, char **argv, char **envp)

  qemu_opts_foreach(qemu_find_opts("chardev"),
    chardev_init_func, NULL, &error_fatal);
-    /* now chardevs have been created we may have semihosting to
connect */
-    qemu_semihosting_connect_chardevs();

  #ifdef CONFIG_VIRTFS
  qemu_opts_foreach(qemu_find_opts("fsdev"),
@@ -4484,6 +4482,9 @@ void qemu_init(int argc, char **argv, char **envp)
  if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
  exit(1);

+    /* now chardevs have been created we may have semihosting to
connect */
+    qemu_semihosting_connect_chardevs();


Cc'ing Markus for this part because he had headaches recently moving
things around there; but the change looks.


+
  /* If no default VGA is requested, the default is "none".  */
  if (default_vga) {
  vga_model = get_default_vga_model(machine_class);

Also I found out that the trailing \0 is sent to the chardev
(console.c:copy_user_string) is that expected in case of semihosting?


No, your patch fixes a bug.


Great thanks for your feedback.




[RFC] some semihosting interrogation

2020-05-28 Thread Fred Konrad

Hi all,

Just wonderring if there is any reason not to be able to defer
qemu_semihosting_connect_chardevs a little more to be able to specify
chardev=serial0?

Like:

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 6390cf0..9fa1553 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4333,8 +4333,6 @@ void qemu_init(int argc, char **argv, char **envp)

 qemu_opts_foreach(qemu_find_opts("chardev"),
   chardev_init_func, NULL, &error_fatal);
-/* now chardevs have been created we may have semihosting to connect */
-qemu_semihosting_connect_chardevs();

 #ifdef CONFIG_VIRTFS
 qemu_opts_foreach(qemu_find_opts("fsdev"),
@@ -4484,6 +4482,9 @@ void qemu_init(int argc, char **argv, char **envp)
 if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
 exit(1);

+/* now chardevs have been created we may have semihosting to connect */
+qemu_semihosting_connect_chardevs();
+
 /* If no default VGA is requested, the default is "none".  */
 if (default_vga) {
 vga_model = get_default_vga_model(machine_class);

Also I found out that the trailing \0 is sent to the chardev 
(console.c:copy_user_string) is that expected in case of semihosting?


static GString *copy_user_string(CPUArchState *env, target_ulong addr)
{
CPUState *cpu = env_cpu(env);
GString *s = g_string_sized_new(128);
uint8_t c;

do {
if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) {
if (c) {
s = g_string_append_c(s, c);
}
} else {
qemu_log_mask(LOG_GUEST_ERROR,
  "%s: passed inaccessible address " TARGET_FMT_lx,
  __func__, addr);
break;
}
} while (c!=0);

return s;
}

I can roll out two patches if needed..

Cheers,
Fred



Re: [PATCH 0/7] hw/sparc/leon3: Few fixes and disable HelenOS test

2020-05-25 Thread Fred Konrad

Sorry Philippe I missed that.

Would be happy to do a PR if needed but:
  * I never did that.
  * Looking at https://wiki.qemu.org/Contribute/SubmitAPullRequest, I don't have
the signed GPG key either.

Cheers,
Fred

Le 5/23/20 à 7:26 PM, Philippe Mathieu-Daudé a écrit :

ping?

On 5/11/20 9:03 AM, Philippe Mathieu-Daudé wrote:

On 4/14/20 12:00 PM, KONRAD Frederic wrote:

Le 4/13/20 à 11:07 PM, Philippe Mathieu-Daudé a écrit :

[Cc'ing Peter]

On 4/13/20 12:12 PM, KONRAD Frederic wrote:

Le 4/11/20 à 7:30 PM, Philippe Mathieu-Daudé a écrit :

On 3/31/20 12:50 PM, Philippe Mathieu-Daudé wrote:

Philippe Mathieu-Daudé (7):
     hw/misc/grlib_ahb_apb_pnp: Avoid crash when writing to AHB PnP
   registers
     hw/misc/grlib_ahb_apb_pnp: Fix AHB PnP 8-bit accesses


Ping ^^^ for 5.0?


Hi Philippe,

You already have my rb tag for those one, and IMHO they should be good
candidate
for 5.0 (if it's not too late).


Yes, thanks for the reviews. I see Mark Cave-Ayland merged this file
first, but you are listed as maintainer :) I was hoping you could send a
pull request.


Yes that's usually Mark who take the patches, sorry I didn't get it.


No worries. As there are other sparc64 patches on the list, maybe Mark
will prepare a pull request now.





$ scripts/get_maintainer.pl -f hw/misc/grlib_ahb_apb_pnp.c
Fabien Chouteau  (maintainer:Leon3)
KONRAD Frederic  (maintainer:Leon3)
qemu-devel@nongnu.org (open list:All patches CC here)




This is a bug but not 'security critical', so it might wait 5.1 and go
via qemu-trivial tree.


Well let's do that then if you're ok.


OK, then ping? :)



Best Regards,
Fred



Regards,

Phil.



Cheers,
Fred




     hw/misc/grlib_ahb_apb_pnp: Add trace events on read accesses
     hw/timer/grlib_gptimer: Display frequency in decimal
     target/sparc/int32_helper: Remove DEBUG_PCALL definition
     target/sparc/int32_helper: Extract and use excp_name_str()

    hw/misc/grlib_ahb_apb_pnp.c | 24
++--
    target/sparc/int32_helper.c | 23
---
    hw/misc/trace-events    |  4 
    hw/timer/trace-events   |  2 +-
    tests/acceptance/machine_sparc_leon3.py |  4 
    5 files changed, 43 insertions(+), 14 deletions(-)











Re: [PATCH] .mailmap: Update Fred Konrad email address

2020-05-18 Thread Fred Konrad

I wasn't aware of this mailmap stuff.

Le 5/18/20 à 12:39 PM, Philippe Mathieu-Daudé a écrit :

Update Fred Konrad email address to avoid emails bouncing.

Signed-off-by: Philippe Mathieu-Daudé 
---
  .mailmap | 1 +
  1 file changed, 1 insertion(+)

diff --git a/.mailmap b/.mailmap
index 6412067bde..4c7f4b7d03 100644
--- a/.mailmap
+++ b/.mailmap
@@ -44,6 +44,7 @@ Aleksandar Markovic  
 
  Aleksandar Rikalo  
  Anthony Liguori  Anthony Liguori 
+Frederic Konrad  
  James Hogan  
  Leif Lindholm  
  Paul Burton  



Reviewed-by: KONRAD Frederic 



Re: [PATCH 02/24] display/xlnx_dp: Fix to realize "i2c-ddc" and "aux-to-i2c-bridge"

2020-05-18 Thread Fred Konrad




Le 5/18/20 à 7:03 AM, Markus Armbruster a écrit :

xlnx_dp_init() creates these two devices, but they're never realized.
Affects machine xlnx-zcu102.

I wonder how this ever worked.  If the "device becomes real only on
realize" thing actually works, then we've always been missing these
two devices, yet nobody noticed.


I can't tell, but it used to work back in 2016 since these devices were required
to have a working framebuffer.



Fix by realizing them in xlnx_dp_realize().

Fixes: 58ac482a66de09a7590f705e53fc6a3fb8a055e8
Cc: KONRAD Frederic 
Cc: Alistair Francis 
Cc: "Edgar E. Iglesias" 
Cc: Peter Maydell 
Cc: qemu-...@nongnu.org
Signed-off-by: Markus Armbruster 
---
  hw/display/xlnx_dp.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 3e5fb44e06..bdc229a51e 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -1264,9 +1264,13 @@ static void xlnx_dp_realize(DeviceState *dev, Error 
**errp)
  DisplaySurface *surface;
  struct audsettings as;
  
+qdev_init_nofail(DEVICE(s->aux_bus->bridge));

+
  qdev_init_nofail(DEVICE(s->dpcd));
  aux_map_slave(AUX_SLAVE(s->dpcd), 0x);
  
+qdev_init_nofail(DEVICE(s->edid));

+
  s->console = graphic_console_init(dev, 0, &xlnx_dp_gfx_ops, s);
  surface = qemu_console_surface(s->console);
  xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,





Re: [PATCH 21/24] sparc/leon3: Fix to put grlib,* devices on sysbus

2020-05-18 Thread Fred Konrad




Le 5/18/20 à 7:04 AM, Markus Armbruster a écrit :

leon3_generic_hw_init() creates a "grlib,ahbpnp" and a "grlib,apbpnp"
sysbus device in a way that leaves them unplugged.

Create them the common way that puts them into the main system bus.
Affects machine leon3_generic.  Visible in "info qtree":

  bus: main-system-bus
type System
 +  dev: grlib,ahbpnp, id ""
 +mmio f000/1000
 +  dev: grlib,apbpnp, id ""
 +mmio 800ff000/1000
dev: grlib,irqmp, id ""

Cc: Fabien Chouteau 
Cc: KONRAD Frederic 
Cc: Mark Cave-Ayland 
Cc: Artyom Tarasenko 
Signed-off-by: Markus Armbruster 
---
  hw/sparc/leon3.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 8f024dab7b..3facb8c2ae 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -213,14 +213,14 @@ static void leon3_generic_hw_init(MachineState *machine)
  reset_info->sp= LEON3_RAM_OFFSET + ram_size;
  qemu_register_reset(main_cpu_reset, reset_info);
  
-ahb_pnp = GRLIB_AHB_PNP(object_new(TYPE_GRLIB_AHB_PNP));

+ahb_pnp = GRLIB_AHB_PNP(qdev_create(NULL, TYPE_GRLIB_AHB_PNP));
  object_property_set_bool(OBJECT(ahb_pnp), true, "realized", &error_fatal);
  sysbus_mmio_map(SYS_BUS_DEVICE(ahb_pnp), 0, LEON3_AHB_PNP_OFFSET);
  grlib_ahb_pnp_add_entry(ahb_pnp, 0, 0, GRLIB_VENDOR_GAISLER,
  GRLIB_LEON3_DEV, GRLIB_AHB_MASTER,
  GRLIB_CPU_AREA);
  
-apb_pnp = GRLIB_APB_PNP(object_new(TYPE_GRLIB_APB_PNP));

+apb_pnp = GRLIB_APB_PNP(qdev_create(NULL, TYPE_GRLIB_APB_PNP));
  object_property_set_bool(OBJECT(apb_pnp), true, "realized", &error_fatal);
  sysbus_mmio_map(SYS_BUS_DEVICE(apb_pnp), 0, LEON3_APB_PNP_OFFSET);
  grlib_ahb_pnp_add_entry(ahb_pnp, LEON3_APB_PNP_OFFSET, 0xFFF,



Reviewed-by: KONRAD Frederic 



[Qemu-devel] [PATCH V3 7/7] xilinx_spips: allow mmio execution

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

This allows to execute from the lqspi area.

When the request_ptr is called the device loads 1024bytes from the SPI device.
Then this code can be executed by the guest.

Reviewed-by: Edgar E. Iglesias 
Signed-off-by: KONRAD Frederic 
---
 hw/ssi/xilinx_spips.c | 74 ++-
 1 file changed, 55 insertions(+), 19 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index da8adfa..e833028 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -496,6 +496,18 @@ static const MemoryRegionOps spips_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
+{
+XilinxSPIPS *s = &q->parent_obj;
+
+if (q->lqspi_cached_addr != ~0ULL) {
+/* Invalidate the current mapped mmio */
+memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
+  LQSPI_CACHE_SIZE);
+q->lqspi_cached_addr = ~0ULL;
+}
+}
+
 static void xilinx_qspips_write(void *opaque, hwaddr addr,
 uint64_t value, unsigned size)
 {
@@ -505,7 +517,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
 addr >>= 2;
 
 if (addr == R_LQSPI_CFG) {
-q->lqspi_cached_addr = ~0ULL;
+xilinx_qspips_invalidate_mmio_ptr(q);
 }
 }
 
@@ -517,27 +529,20 @@ static const MemoryRegionOps qspips_ops = {
 
 #define LQSPI_CACHE_SIZE 1024
 
-static uint64_t
-lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+static void lqspi_load_cache(void *opaque, hwaddr addr)
 {
-int i;
 XilinxQSPIPS *q = opaque;
 XilinxSPIPS *s = opaque;
-uint32_t ret;
-
-if (addr >= q->lqspi_cached_addr &&
-addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
-ret = cpu_to_le32(*(uint32_t *)retp);
-DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
-   (unsigned)ret);
-return ret;
-} else {
-int flash_addr = (addr / num_effective_busses(s));
-int slave = flash_addr >> LQSPI_ADDRESS_BITS;
-int cache_entry = 0;
-uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
-
+int i;
+int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
+   / num_effective_busses(s));
+int slave = flash_addr >> LQSPI_ADDRESS_BITS;
+int cache_entry = 0;
+uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
+
+if (addr < q->lqspi_cached_addr ||
+addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+xilinx_qspips_invalidate_mmio_ptr(q);
 s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
 s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
 
@@ -589,12 +594,43 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 xilinx_spips_update_cs_lines(s);
 
 q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
+}
+}
+
+static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
+unsigned *offset)
+{
+XilinxQSPIPS *q = opaque;
+hwaddr offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
+
+lqspi_load_cache(opaque, offset_within_the_region);
+*size = LQSPI_CACHE_SIZE;
+*offset = offset_within_the_region;
+return q->lqspi_buf;
+}
+
+static uint64_t
+lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+{
+XilinxQSPIPS *q = opaque;
+uint32_t ret;
+
+if (addr >= q->lqspi_cached_addr &&
+addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
+ret = cpu_to_le32(*(uint32_t *)retp);
+DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
+   (unsigned)ret);
+return ret;
+} else {
+lqspi_load_cache(opaque, addr);
 return lqspi_read(opaque, addr, size);
 }
 }
 
 static const MemoryRegionOps lqspi_ops = {
 .read = lqspi_read,
+.request_ptr = lqspi_request_mmio_ptr,
 .endianness = DEVICE_NATIVE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-- 
1.8.3.1




[Qemu-devel] [PATCH V3 6/7] exec: allow to get a pointer for some mmio memory region

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

This introduces a special callback which allows to run code from some MMIO
devices.

SysBusDevice with a MemoryRegion which implements the request_ptr callback will
be notified when the guest try to execute code from their offset. Then it will
be able to eg: pre-load some code from an SPI device or ask a pointer from an
external simulator, etc..

When the pointer or the data in it are no longer valid the device has to
invalidate it.

Signed-off-by: KONRAD Frederic 

V2 -> V3:
  * Put the invalidate in an async work.
  * Clear the dirty flag before dropping the mmio interface.
  * Rebase against recent cpu_handle_unaligned changes.
RFC -> V1:
  * Use mmio-interface instead of directly creating the subregion.
---
 cputlb.c  |  10 +
 include/exec/memory.h |  35 
 memory.c  | 111 ++
 3 files changed, 156 insertions(+)

diff --git a/cputlb.c b/cputlb.c
index 5f6757e..cedac69 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -858,6 +858,16 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
 mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
 if (memory_region_is_unassigned(mr)) {
+qemu_mutex_lock_iothread();
+if (memory_region_request_mmio_ptr(mr, addr)) {
+qemu_mutex_unlock_iothread();
+/* A MemoryRegion is potentially added so re-run the
+ * get_page_addr_code.
+ */
+return get_page_addr_code(env, addr);
+}
+qemu_mutex_unlock_iothread();
+
 cpu_unassigned_access(cpu, addr, false, true, 0, 4);
 /* The CPU's unassigned access hook might have longjumped out
  * with an exception. If it didn't (or there was no hook) then
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 99e0f54..b526f10 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -139,6 +139,15 @@ struct MemoryRegionOps {
 uint64_t data,
 unsigned size,
 MemTxAttrs attrs);
+/* Instruction execution pre-callback:
+ * @addr is the address of the access relative to the @mr.
+ * @size is the size of the area returned by the callback.
+ * @offset is the location of the pointer inside @mr.
+ *
+ * Returns a pointer to a location which contains guest code.
+ */
+void *(*request_ptr)(void *opaque, hwaddr addr, unsigned *size,
+ unsigned *offset);
 
 enum device_endian endianness;
 /* Guest-visible constraints: */
@@ -1353,6 +1362,32 @@ void memory_global_dirty_log_stop(void);
 void mtree_info(fprintf_function mon_printf, void *f, bool flatview);
 
 /**
+ * memory_region_request_mmio_ptr: request a pointer to an mmio
+ * MemoryRegion. If it is possible map a RAM MemoryRegion with this pointer.
+ * When the device wants to invalidate the pointer it will call
+ * memory_region_invalidate_mmio_ptr.
+ *
+ * @mr: #MemoryRegion to check
+ * @addr: address within that region
+ *
+ * Returns true on success, false otherwise.
+ */
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr);
+
+/**
+ * memory_region_invalidate_mmio_ptr: invalidate the pointer to an mmio
+ * previously requested.
+ * In the end that means that if something wants to execute from this area it
+ * will need to request the pointer again.
+ *
+ * @mr: #MemoryRegion associated to the pointer.
+ * @addr: address within that region
+ * @size: size of that area.
+ */
+void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
+   unsigned size);
+
+/**
  * memory_region_dispatch_read: perform a read directly to the specified
  * MemoryRegion.
  *
diff --git a/memory.c b/memory.c
index b727f5e..008b205 100644
--- a/memory.c
+++ b/memory.c
@@ -30,6 +30,8 @@
 #include "exec/ram_addr.h"
 #include "sysemu/kvm.h"
 #include "sysemu/sysemu.h"
+#include "hw/misc/mmio_interface.h"
+#include "hw/qdev-properties.h"
 
 //#define DEBUG_UNASSIGNED
 
@@ -2425,6 +2427,115 @@ void memory_listener_unregister(MemoryListener 
*listener)
 listener->address_space = NULL;
 }
 
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr)
+{
+void *host;
+unsigned size = 0;
+unsigned offset = 0;
+Object *new_interface;
+
+if (!mr || !mr->ops->request_ptr) {
+return false;
+}
+
+/*
+ * Avoid an update if the request_ptr call
+ * memory_region_invalidate_mmio_ptr which seems to be likely when we use
+ * a cache.
+ */
+memory_region_transaction_begin();
+
+host = mr->ops->request_ptr(mr->opaque, addr - mr->addr, &size, &offset);
+
+if (!host || !size) {
+memory_region_transaction_commit();
+return false;
+}
+
+new_interface = object_new("mmio_interface");
+qdev_prop_set_uint64(DE

[Qemu-devel] [PATCH V3 2/7] cputlb: move get_page_addr_code

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

This just moves the code before VICTIM_TLB_HIT macro definition
so we can use it.

Reviewed-by: Richard Henderson 
Reviewed-by: Edgar E. Iglesias 
Signed-off-by: KONRAD Frederic 

V2 -> V3:
  * Rebase against cpu_unaligned access recent change.
---
 cputlb.c | 70 
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index dcf28f7..ad1d983 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -746,41 +746,6 @@ static inline ram_addr_t 
qemu_ram_addr_from_host_nofail(void *ptr)
 return ram_addr;
 }
 
-/* NOTE: this function can trigger an exception */
-/* NOTE2: the returned address is not exactly the physical address: it
- * is actually a ram_addr_t (in system mode; the user mode emulation
- * version of this function returns a guest virtual address).
- */
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
-{
-int mmu_idx, index, pd;
-void *p;
-MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env);
-CPUIOTLBEntry *iotlbentry;
-
-index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env, true);
-if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
-}
-iotlbentry = &env->iotlb[mmu_idx][index];
-pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
-if (memory_region_is_unassigned(mr)) {
-cpu_unassigned_access(cpu, addr, false, true, 0, 4);
-/* The CPU's unassigned access hook might have longjumped out
- * with an exception. If it didn't (or there was no hook) then
- * we can't proceed further.
- */
-report_bad_exec(cpu, addr);
-exit(1);
-}
-p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
-return qemu_ram_addr_from_host_nofail(p);
-}
-
 static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
  target_ulong addr, uintptr_t retaddr, int size)
 {
@@ -868,6 +833,41 @@ static bool victim_tlb_hit(CPUArchState *env, size_t 
mmu_idx, size_t index,
   victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
  (ADDR) & TARGET_PAGE_MASK)
 
+/* NOTE: this function can trigger an exception */
+/* NOTE2: the returned address is not exactly the physical address: it
+ * is actually a ram_addr_t (in system mode; the user mode emulation
+ * version of this function returns a guest virtual address).
+ */
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
+{
+int mmu_idx, index, pd;
+void *p;
+MemoryRegion *mr;
+CPUState *cpu = ENV_GET_CPU(env);
+CPUIOTLBEntry *iotlbentry;
+
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
+ (addr & TARGET_PAGE_MASK))) {
+cpu_ldub_code(env, addr);
+}
+iotlbentry = &env->iotlb[mmu_idx][index];
+pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
+mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
+if (memory_region_is_unassigned(mr)) {
+cpu_unassigned_access(cpu, addr, false, true, 0, 4);
+/* The CPU's unassigned access hook might have longjumped out
+ * with an exception. If it didn't (or there was no hook) then
+ * we can't proceed further.
+ */
+report_bad_exec(cpu, addr);
+exit(1);
+}
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
+return qemu_ram_addr_from_host_nofail(p);
+}
+
 /* Probe for whether the specified guest write access is permitted.
  * If it is not permitted then an exception will be taken in the same
  * way as if this were a real write access (and we will not return).
-- 
1.8.3.1




[Qemu-devel] [PATCH V3 3/7] cputlb: fix the way get_page_addr_code fills the tlb

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

get_page_addr_code(..) does a cpu_ldub_code to fill the tlb:
This can lead to some side effects if a device is mapped at this address.

So this patch replaces the cpu_memory_ld by a tlb_fill.

Reviewed-by: Richard Henderson 
Reviewed-by: Edgar E. Iglesias 
Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index ad1d983..5f6757e 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -849,8 +849,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 mmu_idx = cpu_mmu_index(env, true);
 if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
+ (addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK {
+if (!VICTIM_TLB_HIT(addr_read, addr)) {
+tlb_fill(ENV_GET_CPU(env), addr, MMU_INST_FETCH, mmu_idx, 0);
+}
 }
 iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-- 
1.8.3.1




[Qemu-devel] [PATCH V3 1/7] cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

This replaces env1 and page_index variables by env and index
so we can use VICTIM_TLB_HIT macro later.

Reviewed-by: Richard Henderson 
Reviewed-by: Edgar E. Iglesias 
Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index f5d056c..dcf28f7 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -751,21 +751,21 @@ static inline ram_addr_t 
qemu_ram_addr_from_host_nofail(void *ptr)
  * is actually a ram_addr_t (in system mode; the user mode emulation
  * version of this function returns a guest virtual address).
  */
-tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
 {
-int mmu_idx, page_index, pd;
+int mmu_idx, index, pd;
 void *p;
 MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env1);
+CPUState *cpu = ENV_GET_CPU(env);
 CPUIOTLBEntry *iotlbentry;
 
-page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env1, true);
-if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
  (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env1, addr);
+cpu_ldub_code(env, addr);
 }
-iotlbentry = &env1->iotlb[mmu_idx][page_index];
+iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
 mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
 if (memory_region_is_unassigned(mr)) {
@@ -777,7 +777,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, 
target_ulong addr)
 report_bad_exec(cpu, addr);
 exit(1);
 }
-p = (void *)((uintptr_t)addr + 
env1->tlb_table[mmu_idx][page_index].addend);
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
 return qemu_ram_addr_from_host_nofail(p);
 }
 
-- 
1.8.3.1




[Qemu-devel] [PATCH V3 5/7] introduce mmio_interface

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

This introduces mmio_interface object which contains a MemoryRegion
and can be hotplugged/hotunplugged.

Reviewed-by: Edgar E. Iglesias 
Signed-off-by: KONRAD Frederic 

V1 -> V2:
  * Fix the qemu_log format.
---
 hw/misc/Makefile.objs|   1 +
 hw/misc/mmio_interface.c | 128 +++
 include/hw/misc/mmio_interface.h |  49 +++
 3 files changed, 178 insertions(+)
 create mode 100644 hw/misc/mmio_interface.c
 create mode 100644 include/hw/misc/mmio_interface.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c8b4893..7317dce 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -56,3 +56,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-y += mmio_interface.o
diff --git a/hw/misc/mmio_interface.c b/hw/misc/mmio_interface.c
new file mode 100644
index 000..6f004d2
--- /dev/null
+++ b/hw/misc/mmio_interface.c
@@ -0,0 +1,128 @@
+/*
+ * mmio_interface.c
+ *
+ *  Copyright (C) 2017 : GreenSocs
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option)any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/mmio_interface.h"
+#include "qapi/error.h"
+
+#ifndef DEBUG_MMIO_INTERFACE
+#define DEBUG_MMIO_INTERFACE 0
+#endif
+
+static uint64_t mmio_interface_counter;
+
+#define DPRINTF(fmt, ...) do { 
\
+if (DEBUG_MMIO_INTERFACE) {
\
+qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## 
__VA_ARGS__);\
+}  
\
+} while (0);
+
+static void mmio_interface_init(Object *obj)
+{
+MMIOInterface *s = MMIO_INTERFACE(obj);
+
+if (DEBUG_MMIO_INTERFACE) {
+s->id = mmio_interface_counter++;
+}
+
+DPRINTF("interface created\n");
+s->host_ptr = 0;
+s->subregion = 0;
+}
+
+static void mmio_interface_realize(DeviceState *dev, Error **errp)
+{
+MMIOInterface *s = MMIO_INTERFACE(dev);
+
+DPRINTF("realize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+
+if (!s->host_ptr) {
+error_setg(errp, "host_ptr property must be set");
+}
+
+if (!s->subregion) {
+error_setg(errp, "subregion property must be set");
+}
+
+memory_region_init_ram_ptr(&s->ram_mem, OBJECT(s), "ram",
+   s->end - s->start + 1, s->host_ptr);
+memory_region_set_readonly(&s->ram_mem, s->ro);
+memory_region_add_subregion(s->subregion, s->start, &s->ram_mem);
+}
+
+static void mmio_interface_unrealize(DeviceState *dev, Error **errp)
+{
+MMIOInterface *s = MMIO_INTERFACE(dev);
+
+DPRINTF("unrealize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+memory_region_del_subregion(s->subregion, &s->ram_mem);
+}
+
+static void mmio_interface_finalize(Object *obj)
+{
+MMIOInterface *s = MMIO_INTERFACE(obj);
+
+DPRINTF("finalize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+object_unparent(OBJECT(&s->ram_mem));
+}
+
+static Property mmio_interface_properties[] = {
+DEFINE_PROP_UINT64("start", MMIOInterface, start, 0),
+DEFINE_PROP_UINT64("end", MMIOInterface, end, 0),
+DEFINE_PROP_PTR("host_ptr", MMIOInterface, host_ptr),
+DEFINE_PROP_BOOL("ro", MMIOInterface, ro, false),
+DEFINE_PROP_MEMORY_REGION("subregion", MMIOInterface, subregion),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mmio_interface_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = mmio_interface_realize;
+dc->unrealize = mmio_interface_unrealize;
+dc->props = mmio_interface_properties;
+}
+
+static const TypeInfo mmio_interface_info = {
+.name  = TYPE_MMIO_INTERFACE,
+.parent= TYPE_DEVICE,
+.instance_size = sizeof(MMIOInterface),
+.instance_init = mmio_interface_init,
+.instance_finalize = mmio

[Qemu-devel] [PATCH V3 0/7] execute code from mmio area

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

This series allows to execute code from mmio areas.
The main goal of this is to be able to run code for example from an SPI device.

The three first patch fixes the way get_page_addr_code fills the TLB.

The sixth patch implements the mmio execution helpers: the device must
implement the request_ptr callback of the MemoryRegion and will be notified
when the guest wants to execute code from it.

The fouth and fifth patch introduces mmio_interface device which allows to
dynamically map a host pointer somewhere into the memory.

The last patch implements the execution from the SPI memories in the
xilinx_spips model.

Thanks,
Fred

V2 -> V3:
  * Reorder patches to allow bisection.
  * Rebase on current master.
  * Use an async work to invalidate the mmio region.
  * Clear the dirty of the region before invalidating it.
V1 -> V2:
  * Fix the DPRINTF error.
RFC -> V1:
  * Use an interface (mmio-interface) to fix any reference leak issue.

KONRAD Frederic (7):
  cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT
  cputlb: move get_page_addr_code
  cputlb: fix the way get_page_addr_code fills the tlb
  qdev: add MemoryRegion property
  introduce mmio_interface
  exec: allow to get a pointer for some mmio memory region
  xilinx_spips: allow mmio execution

 cputlb.c |  82 ++---
 hw/misc/Makefile.objs|   1 +
 hw/misc/mmio_interface.c | 128 +++
 hw/ssi/xilinx_spips.c|  74 --
 include/exec/memory.h|  35 +++
 include/hw/misc/mmio_interface.h |  49 +++
 include/hw/qdev-properties.h |   2 +
 memory.c | 111 +
 8 files changed, 428 insertions(+), 54 deletions(-)
 create mode 100644 hw/misc/mmio_interface.c
 create mode 100644 include/hw/misc/mmio_interface.h

-- 
1.8.3.1




[Qemu-devel] [PATCH V3 4/7] qdev: add MemoryRegion property

2017-04-28 Thread fred . konrad
From: KONRAD Frederic 

We need to pass a pointer to a MemoryRegion for mmio_interface.
So this just adds that.

Reviewed-by: Edgar E. Iglesias 
Signed-off-by: KONRAD Frederic 
---
 include/hw/qdev-properties.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 1d69fa7..57d5331 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -171,6 +171,8 @@ extern PropertyInfo qdev_prop_arraylen;
 DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
 #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
 DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+#define DEFINE_PROP_MEMORY_REGION(_n, _s, _f) \
+DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, MemoryRegion *)
 
 #define DEFINE_PROP_END_OF_LIST()   \
 {}
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc_booke: drop useless assignment

2017-03-24 Thread fred . konrad
From: KONRAD Frederic 

The tb_env variable is set two lines above. So just drop the double assignment.

Signed-off-by: KONRAD Frederic 
---
 hw/ppc/ppc_booke.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index 60baffa..23bcf1b 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -282,7 +282,6 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
 ppc_tb_t *tb_env = env->tb_env;
 booke_timer_t *booke_timer = tb_env->opaque;
 
-tb_env = env->tb_env;
 env->spr[SPR_BOOKE_TCR] = val;
 kvmppc_set_tcr(cpu);
 
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 04/10] qemu-clk: introduce an init array to help the device construction

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This introduces a clock init array to ease the clock tree construction.

Signed-off-by: KONRAD Frederic 

V2 -> V3:
  * s/QEMUClock/qemu_clk/g
---
 include/qemu/qemu-clock.h | 23 +++
 qemu-clock.c  | 17 +
 2 files changed, 40 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index f80de56..1c57df4 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -49,6 +49,29 @@ struct ClkList {
 QLIST_ENTRY(ClkList) node;
 };
 
+typedef struct ClockInitElement {
+const char *name;  /* Name to give to the clock. */
+size_t offset; /* Offset of the qemu_clk field in the object. */
+QEMUClkRateUpdateCallback *cb;
+} ClockInitElement;
+
+#define DEVICE_CLOCK(_state, _field, _cb) {  \
+.name = #_field, \
+.offset = offsetof(_state, _field),  \
+.cb = _cb\
+}
+
+#define DEVICE_CLOCK_END() { \
+.name = NULL \
+}
+
+/**
+ * qemu_clk_init_device:
+ * @obj: the Object which need to be initialized.
+ * @array: the array of ClockInitElement to be used.
+ */
+void qemu_clk_init_device(Object *obj, ClockInitElement *array);
+
 /**
  * qemu_clk_device_add_clock:
  * @dev: the device on which the clock needs to be added.
diff --git a/qemu-clock.c b/qemu-clock.c
index 24719e2..8f342f6 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -26,6 +26,7 @@
 #include "hw/hw.h"
 #include "qemu/log.h"
 #include "qapi/error.h"
+#include "hw/qdev-core.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -37,6 +38,22 @@
 }\
 } while (0);
 
+void qemu_clk_init_device(Object *obj, ClockInitElement *array)
+{
+QEMUClock **cur = NULL;
+
+while (array->name != NULL) {
+DPRINTF("init clock named %s\n", array->name);
+cur = (((void *)obj) + array->offset);
+*cur = QEMU_CLOCK(object_new(TYPE_CLOCK));
+qemu_clk_device_add_clock(DEVICE(obj), *cur, array->name);
+if (array->cb) {
+qemu_clk_set_callback(*cur, array->cb, obj);
+}
+array++;
+}
+}
+
 void qemu_clk_refresh(QEMUClock *clk)
 {
 qemu_clk_update_rate(clk, clk->ref_rate);
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 01/10] qemu-clk: introduce qemu-clk qom object

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This introduces qemu-clk qom object.

Signed-off-by: KONRAD Frederic 

V2 -> V3:
  * s/qemu_clk/QEMUClock/g
---
 Makefile.objs |  1 +
 include/qemu/qemu-clock.h | 40 +
 qemu-clock.c  | 50 +++
 3 files changed, 91 insertions(+)
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

diff --git a/Makefile.objs b/Makefile.objs
index e740500..0b8b8ff 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -75,6 +75,7 @@ common-obj-y += backends/
 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
 
 common-obj-$(CONFIG_FDT) += device_tree.o
+common-obj-y += qemu-clock.o
 
 ##
 # qapi
diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
new file mode 100644
index 000..446a490
--- /dev/null
+++ b/include/qemu/qemu-clock.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef QEMU_CLOCK_H
+#define QEMU_CLOCK_H
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+
+#define TYPE_CLOCK "qemu-clk"
+#define QEMU_CLOCK(obj) OBJECT_CHECK(QEMUClock, (obj), TYPE_CLOCK)
+
+typedef struct QEMUClock {
+/*< private >*/
+Object parent_obj;
+} QEMUClock;
+
+#endif /* QEMU_CLOCK_H */
+
+
diff --git a/qemu-clock.c b/qemu-clock.c
new file mode 100644
index 000..3bef144
--- /dev/null
+++ b/qemu-clock.c
@@ -0,0 +1,50 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/qemu-clock.h"
+#include "hw/hw.h"
+#include "qemu/log.h"
+
+#ifndef DEBUG_QEMU_CLOCK
+#define DEBUG_QEMU_CLOCK 0
+#endif
+
+#define DPRINTF(fmt, args...) do {   \
+if (DEBUG_QEMU_CLOCK) {  \
+qemu_log("%s: " fmt, __func__, ## args); \
+}\
+} while (0);
+
+static const TypeInfo qemu_clk_info = {
+.name  = TYPE_CLOCK,
+.parent= TYPE_OBJECT,
+.instance_size = sizeof(QEMUClock),
+};
+
+static void qemu_clk_register_types(void)
+{
+type_register_static(&qemu_clk_info);
+}
+
+type_init(qemu_clk_register_types);
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 10/10] zynqmp: add reference clock

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This adds some fixed reference clock to the zynqmp platform.
They will feed the zynqmp_crf block.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 49 
 include/hw/arm/xlnx-zynqmp.h |  6 ++
 2 files changed, 55 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 27dccdb..b9cd856 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -24,6 +24,7 @@
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
+#include "qemu/qemu-clock.h"
 
 #define GIC_NUM_SPI_INTR 160
 
@@ -182,6 +183,22 @@ static void xlnx_zynqmp_init(Object *obj)
 qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
 object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
   &error_abort);
+
+s->pss_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_ref_clk", s->pss_ref_clk,
+  &error_abort);
+object_property_set_int(s->pss_ref_clk, 5000, "rate", &error_abort);
+s->video_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "video_clk", s->video_clk, &error_abort);
+object_property_set_int(s->video_clk, 2700, "rate", &error_abort);
+s->pss_alt_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_alt_ref_clk", s->pss_alt_ref_clk,
+  &error_abort);
+s->aux_refclk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "aux_refclk", s->aux_refclk, &error_abort);
+s->gt_crx_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "gt_crx_ref_clk", s->gt_crx_ref_clk,
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -431,6 +448,38 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
+
+/* Bind the clock */
+qemu_clk_bind(qemu_clk_device_get_clock(DEVICE(s->pss_ref_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "pss_ref_clk"));
+
+qemu_clk_bind(qemu_clk_device_get_clock(DEVICE(s->video_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf), 
"video_clk"));
+
+qemu_clk_bind(qemu_clk_device_get_clock(DEVICE(s->pss_alt_ref_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "pss_alt_ref_clk"));
+
+qemu_clk_bind(qemu_clk_device_get_clock(DEVICE(s->aux_refclk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "aux_refclk"));
+
+qemu_clk_bind(qemu_clk_device_get_clock(DEVICE(s->gt_crx_ref_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "gt_crx_ref_clk"));
+
+object_property_set_bool(s->crf, true, "realized", &err);
+object_property_set_bool(s->pss_ref_clk, true, "realized", &err);
+object_property_set_bool(s->video_clk, true, "realized", &err);
+object_property_set_bool(s->pss_alt_ref_clk, true, "realized", &err);
+object_property_set_bool(s->aux_refclk, true, "realized", &err);
+object_property_set_bool(s->gt_crx_ref_clk, true, "realized", &err);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 379a17a..d0cc57f 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -28,6 +28,7 @@
 #include "hw/ssi/xilinx_spips.h"
 #include "hw/dma/xlnx_dpdma.h"
 #include "hw/display/xlnx_dp.h"
+#include "hw/misc/fixed-clock.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
@@ -86,6 +87,11 @@ typedef struct XlnxZynqMPState {
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
+Object *pss_ref_clk;
+Object *video_clk;
+Object *pss_alt_ref_clk;
+Object *aux_refclk;
+Object *gt_crx_ref_clk;
 Object *crf;
 
 char *boot_cpu;
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 00/10] Clock framework API.

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

Hi,

This is the third version of the clock framework API it contains:

  * The first 6 patches which introduce the framework.
  * The 7th patch which introduces a fixed-clock model.
  * The rest which gives an example how to model a PLL from the existing
zynqmp-crf extracted from the qemu xilinx tree.

No specific behavior is expected yet when the CRF register set is accessed but
the user can see for example the dp_video_ref and vpll_to_lpd rate changing in
the monitor with the "info qtree" command when the vpll_ctrl register is
modified.

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
qemu-clk "dbg_trace" 0
qemu-clk "dp_stc_ref" 0
qemu-clk "dpll_to_lpd" 1250
qemu-clk "acpu_clk" 0
qemu-clk "pcie_ref" 0
qemu-clk "topsw_main" 0
qemu-clk "topsw_lsbus" 0
qemu-clk "dp_audio_ref" 0
qemu-clk "sata_ref" 0
qemu-clk "dp_video_ref" 1428571
qemu-clk "vpll_clk" 5000
qemu-clk "apll_to_lpd" 1250
qemu-clk "dpll_clk" 5000
qemu-clk "gpu_ref" 0
qemu-clk "aux_refclk" 0
qemu-clk "video_clk" 2700
qemu-clk "gdma_ref" 0
qemu-clk "gt_crx_ref_clk" 0
qemu-clk "dbg_fdp" 0
qemu-clk "apll_clk" 5000
qemu-clk "pss_alt_ref_clk" 0
qemu-clk "ddr" 0
qemu-clk "dbg_tstmp" 0
qemu-clk "pss_ref_clk" 5000
qemu-clk "dpdma_ref" 0
qemu-clk "vpll_to_lpd" 1250
mmio fd1a/010c

This series is based on the current master
(d992f2f1368ceb92e6bfd8efece174110f4236ff).

Thanks,
Fred

V2 -> V3:
  * Rebased on current master.
  * Renamed qemu_clk / QEMUClock as suggested by Cédric.
  * Renamed in_rate to ref_rate and out_rate to rate.
  * Renamed qemu_clk_bind_clock to qemu_clk_bind.
  * Example added to the documentation as suggested by Peter.

V1 -> V2:
  * Rebased on current master.
  * Some function renamed and documentation fixed.

RFC -> V1:
  * Rebased on current master.
  * The docs has been fixed.
  * qemu_clk_init_device helper has been provided to ease the initialization
of the devices.

KONRAD Frederic (10):
  qemu-clk: introduce qemu-clk qom object
  qemu-clk: allow to add a clock to a device
  qemu-clk: allow to bind two clocks together
  qemu-clk: introduce an init array to help the device construction
  qdev-monitor: print the device's clock with info qtree
  docs: add qemu-clock documentation
  introduce fixed-clock
  introduce zynqmp_crf
  zynqmp: add the zynqmp_crf to the platform
  zynqmp: add reference clock

 Makefile.objs |   1 +
 docs/clock.txt| 278 
 hw/arm/xlnx-zynqmp.c  |  56 +++
 hw/misc/Makefile.objs |   2 +
 hw/misc/fixed-clock.c |  88 
 hw/misc/xilinx_zynqmp_crf.c   | 968 ++
 include/hw/arm/xlnx-zynqmp.h  |   8 +
 include/hw/misc/fixed-clock.h |  30 ++
 include/qemu/qemu-clock.h | 161 +++
 qdev-monitor.c|   2 +
 qemu-clock.c  | 176 
 11 files changed, 1770 insertions(+)
 create mode 100644 docs/clock.txt
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c
 create mode 100644 include/hw/misc/fixed-clock.h
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

-- 
1.8.3.1




[Qemu-devel] [PATCH v3 08/10] introduce zynqmp_crf

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This introduce Xilinx zynqmp-crf.
It is extracted from the qemu xilinx tree 
(02d2f0203dd489ed30d9c8d90c14a52c57332b25) and is used as
an example for the clock framework.
---
 hw/misc/Makefile.objs   |   1 +
 hw/misc/xilinx_zynqmp_crf.c | 968 
 2 files changed, 969 insertions(+)
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index e9c4dd3..92cdb40 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -45,6 +45,7 @@ obj-$(CONFIG_RASPI) += bcm2835_property.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
+obj-$(CONFIG_ZYNQ) += xilinx_zynqmp_crf.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
diff --git a/hw/misc/xilinx_zynqmp_crf.c b/hw/misc/xilinx_zynqmp_crf.c
new file mode 100644
index 000..fa3a9cb
--- /dev/null
+++ b/hw/misc/xilinx_zynqmp_crf.c
@@ -0,0 +1,968 @@
+/*
+ * QEMU model of the CRF_APB APB control registers for clock controller. The
+ * RST_ctrl_fpd will be added to this as well
+ *
+ * Copyright (c) 2014 Xilinx Inc.
+ *
+ * Autogenerated by xregqemu.py 2014-01-22.
+ *
+ * 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/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/qemu-clock.h"
+
+#ifndef XILINX_CRF_APB_ERR_DEBUG
+#define XILINX_CRF_APB_ERR_DEBUG 0
+#endif
+
+#define TYPE_XILINX_CRF_APB "xlnx.zynqmp_crf"
+
+#define XILINX_CRF_APB(obj) \
+ OBJECT_CHECK(CRF_APB, (obj), TYPE_XILINX_CRF_APB)
+
+REG32(ERR_CTRL, 0x0)
+FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x4)
+FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_MASK, 0x8)
+FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_ENABLE, 0xc)
+FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_DISABLE, 0x10)
+FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(CRF_ECO, 0x18)
+REG32(APLL_CTRL, 0x20)
+FIELD(APLL_CTRL, POST_SRC, 24, 3)
+FIELD(APLL_CTRL, PRE_SRC, 20, 3)
+FIELD(APLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(APLL_CTRL, DIV2, 16, 1)
+FIELD(APLL_CTRL, FBDIV, 8, 7)
+FIELD(APLL_CTRL, BYPASS, 3, 1)
+FIELD(APLL_CTRL, RESET, 0, 1)
+REG32(APLL_CFG, 0x24)
+FIELD(APLL_CFG, LOCK_DLY, 25, 7)
+FIELD(APLL_CFG, LOCK_CNT, 13, 10)
+FIELD(APLL_CFG, LFHF, 10, 2)
+FIELD(APLL_CFG, CP, 5, 4)
+FIELD(APLL_CFG, RES, 0, 4)
+REG32(APLL_FRAC_CFG, 0x28)
+FIELD(APLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(APLL_FRAC_CFG, SEED, 22, 3)
+FIELD(APLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(APLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(APLL_FRAC_CFG, DATA, 0, 16)
+REG32(DPLL_CTRL, 0x2c)
+FIELD(DPLL_CTRL, POST_SRC, 24, 3)
+FIELD(DPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(DPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(DPLL_CTRL, DIV2, 16, 1)
+FIELD(DPLL_CTRL, FBDIV, 8, 7)
+FIELD(DPLL_CTRL, BYPASS, 3, 1)
+FIELD(DPLL_CTRL, RESET, 0, 1)
+REG32(DPLL_CFG, 0x30)
+FIELD(DPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(DPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(DPLL_CFG, LFHF, 10, 2)
+FIELD(DPLL_CFG, CP, 5, 4)
+FIELD(DPLL_CFG, RES, 0, 4)
+REG32(DPLL_FRAC_CFG, 0x34)
+FIELD(DPLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(DPLL_FRAC_CFG, SEED, 22, 3)
+FIELD(DPLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(DPLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(DPLL_FRAC_CFG, DATA, 0, 16)
+REG32(VPLL_CTRL, 0x38)
+FIELD(VPLL_CTRL, POST_SRC, 24, 3)
+FIELD(VPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(VPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(VPLL_CTRL, DIV2, 16, 1)
+FIELD(VPLL_CTRL, FBDIV, 8, 7)
+FIELD(VPLL_CTRL, BYPASS, 3, 1)
+FIELD(VPLL_CTRL, RESET, 0, 1)
+REG32(VPLL_CFG, 0x3c)
+FIELD(VPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(VPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(VPLL_CFG, LFHF, 10, 2)
+FIELD(VPLL_CFG, CP, 5, 4)
+FIELD(VP

[Qemu-devel] [PATCH v3 07/10] introduce fixed-clock

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This is a fixed clock device.
It justs behave as an empty device with a parametrable output rate.

Signed-off-by: KONRAD Frederic 
---
 hw/misc/Makefile.objs |  1 +
 hw/misc/fixed-clock.c | 88 +++
 include/hw/misc/fixed-clock.h | 30 +++
 3 files changed, 119 insertions(+)
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 include/hw/misc/fixed-clock.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 898e4cc..e9c4dd3 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -55,3 +55,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-y += fixed-clock.o
diff --git a/hw/misc/fixed-clock.c b/hw/misc/fixed-clock.c
new file mode 100644
index 000..b5af24d
--- /dev/null
+++ b/hw/misc/fixed-clock.c
@@ -0,0 +1,88 @@
+/*
+ * Fixed clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev.h"
+#include "hw/misc/fixed-clock.h"
+#include "qemu/qemu-clock.h"
+#include "qapi/error.h"
+
+#ifndef DEBUG_FIXED_CLOCK
+#define DEBUG_FIXED_CLOCK 0
+#endif
+
+#define DPRINTF(fmt, ...) do {   \
+if (DEBUG_FIXED_CLOCK) { \
+qemu_log(__FILE__": " fmt , ## __VA_ARGS__); \
+}\
+} while (0);
+
+typedef struct {
+DeviceState parent_obj;
+
+uint32_t rate;
+QEMUClock out;
+} FixedClock;
+
+static Property fixed_clock_properties[] = {
+DEFINE_PROP_UINT32("rate", FixedClock, rate, 0),
+DEFINE_PROP_END_OF_LIST()
+};
+
+static void fixed_clock_realizefn(DeviceState *dev, Error **errp)
+{
+FixedClock *s = FIXED_CLOCK(dev);
+
+qemu_clk_update_rate(&s->out, s->rate);
+}
+
+static void fixed_clock_instance_init(Object *obj)
+{
+FixedClock *s = FIXED_CLOCK(obj);
+
+object_initialize(&s->out, sizeof(s->out), TYPE_CLOCK);
+qemu_clk_device_add_clock(DEVICE(obj), &s->out, "clk_out");
+}
+
+static void fixed_clock_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = fixed_clock_realizefn;
+dc->props = fixed_clock_properties;
+}
+
+static const TypeInfo fixed_clock_info = {
+.name  = TYPE_FIXED_CLOCK,
+.parent= TYPE_DEVICE,
+.instance_size = sizeof(FixedClock),
+.instance_init = fixed_clock_instance_init,
+.class_init= fixed_clock_class_init,
+};
+
+static void fixed_clock_register_types(void)
+{
+type_register_static(&fixed_clock_info);
+}
+
+type_init(fixed_clock_register_types);
diff --git a/include/hw/misc/fixed-clock.h b/include/hw/misc/fixed-clock.h
new file mode 100644
index 000..1376444
--- /dev/null
+++ b/include/hw/misc/fixed-clock.h
@@ -0,0 +1,30 @@
+/*
+ * Fixed clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef FIXED_CLOCK_H
+#define FIXED_CLOCK_H
+
+#define TYPE_FIXED_CLOCK "fixed-clock"
+#define FIXED_CLOCK(obj) OBJECT_CHECK(FixedClock, (obj), TYPE_FIXED_CLOCK)
+
+#endif /* FIXED_CLOCK_H */
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 09/10] zynqmp: add the zynqmp_crf to the platform

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This adds the zynqmp_crf to the zynqmp platform.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 7 +++
 include/hw/arm/xlnx-zynqmp.h | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index bc4e66b..27dccdb 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -177,6 +177,11 @@ static void xlnx_zynqmp_init(Object *obj)
 
 object_initialize(&s->dpdma, sizeof(s->dpdma), TYPE_XLNX_DPDMA);
 qdev_set_parent_bus(DEVICE(&s->dpdma), sysbus_get_default());
+
+s->crf = object_new("xlnx.zynqmp_crf");
+qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
+object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -424,6 +429,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
  &error_abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->dpdma), 0, DPDMA_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
+
+sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index c2931bf..379a17a 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -86,6 +86,8 @@ typedef struct XlnxZynqMPState {
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
+Object *crf;
+
 char *boot_cpu;
 ARMCPU *boot_cpu_ptr;
 
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 03/10] qemu-clk: allow to bind two clocks together

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This introduces the clock binding and the update part.
When the qemu_clk_rate_update(qemu_clk, int) function is called:
  * The clock callback is called on the qemu_clk so it can change the rate.
  * The qemu_clk_rate_update function is called on all the driven clock.

Signed-off-by: KONRAD Frederic 

V2 -> V3:
  * s/qemu_clk/QEMUClock/g
  * Rename in_rate to ref_rate
  * Rename out_rate to rate
  * Rename qemu_clk_bind_clock to qemu_clk_bind
V1 -> V2:
  * Rename qemu_clk_on_rate_update_cb to QEMUClkRateUpdateCallback and
move the pointer to the structure instead of having a pointer-to-function
type.
---
 include/qemu/qemu-clock.h | 67 +++
 qemu-clock.c  | 58 
 2 files changed, 125 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index ffe743d..f80de56 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -30,12 +30,25 @@
 #define TYPE_CLOCK "qemu-clk"
 #define QEMU_CLOCK(obj) OBJECT_CHECK(QEMUClock, (obj), TYPE_CLOCK)
 
+typedef struct ClkList ClkList;
+typedef uint64_t QEMUClkRateUpdateCallback(void *opaque, uint64_t rate);
+
 typedef struct QEMUClock {
 /*< private >*/
 Object parent_obj;
 char *name;/* name of this clock in the device. */
+uint64_t ref_rate; /* rate of the clock which drive this pin. */
+uint64_t rate; /* rate of this clock pin. */
+void *opaque;
+QEMUClkRateUpdateCallback *cb;
+QLIST_HEAD(, ClkList) bound;
 } QEMUClock;
 
+struct ClkList {
+QEMUClock *clk;
+QLIST_ENTRY(ClkList) node;
+};
+
 /**
  * qemu_clk_device_add_clock:
  * @dev: the device on which the clock needs to be added.
@@ -59,4 +72,58 @@ void qemu_clk_device_add_clock(DeviceState *dev, QEMUClock 
*clk,
  */
 QEMUClock *qemu_clk_device_get_clock(DeviceState *dev, const char *name);
 
+/**
+ * qemu_clk_bind:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Connect the clock together. This is unidirectional so a
+ * qemu_clk_update_rate will go from @out to @in.
+ *
+ */
+void qemu_clk_bind(QEMUClock *out, QEMUClock *in);
+
+/**
+ * qemu_clk_unbind:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Disconnect the clocks if they were bound together.
+ *
+ */
+void qemu_clk_unbind(QEMUClock *out, QEMUClock *in);
+
+/**
+ * qemu_clk_update_rate:
+ * @clk: the clock to update.
+ * @rate: the new rate in Hz.
+ *
+ * Update the @clk to the new @rate.
+ *
+ */
+void qemu_clk_update_rate(QEMUClock *clk, uint64_t rate);
+
+/**
+ * qemu_clk_refresh:
+ * @clk: the clock to be refreshed.
+ *
+ * If a model alters the topology of a clock tree, it must call this function 
on
+ * the clock source to refresh the clock tree.
+ *
+ */
+void qemu_clk_refresh(QEMUClock *clk);
+
+/**
+ * qemu_clk_set_callback:
+ * @clk: the clock associated to the callback.
+ * @cb: the function which is called when a refresh happen on the clock @clk.
+ * @opaque: the opaque data passed to the callback.
+ *
+ * Set the callback @cb which will be called when the clock @clk is updated.
+ *
+ */
+void qemu_clk_set_callback(QEMUClock *clk,
+   QEMUClkRateUpdateCallback *cb,
+   void *opaque);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index 6eeecf3..24719e2 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -37,6 +37,64 @@
 }\
 } while (0);
 
+void qemu_clk_refresh(QEMUClock *clk)
+{
+qemu_clk_update_rate(clk, clk->ref_rate);
+}
+
+void qemu_clk_update_rate(QEMUClock *clk, uint64_t rate)
+{
+ClkList *child;
+
+clk->ref_rate = rate;
+clk->rate = rate;
+
+if (clk->cb) {
+clk->rate = clk->cb(clk->opaque, rate);
+}
+
+DPRINTF("%s output rate updated to %" PRIu64 "\n",
+object_get_canonical_path(OBJECT(clk)),
+clk->rate);
+
+QLIST_FOREACH(child, &clk->bound, node) {
+qemu_clk_update_rate(child->clk, clk->rate);
+}
+}
+
+void qemu_clk_bind(QEMUClock *out, QEMUClock *in)
+{
+ClkList *child;
+
+child = g_malloc(sizeof(child));
+assert(child);
+child->clk = in;
+object_ref(OBJECT(in));
+QLIST_INSERT_HEAD(&out->bound, child, node);
+qemu_clk_update_rate(in, out->rate);
+}
+
+void qemu_clk_unbind(QEMUClock *out, QEMUClock *in)
+{
+ClkList *child, *next;
+
+QLIST_FOREACH_SAFE(child, &out->bound, node, next) {
+if (child->clk == in) {
+QLIST_REMOVE(child, node);
+g_free(child);
+object_unref(OBJECT(in));
+}
+}
+}
+
+void qemu_clk_set_callback(QEMUClock *clk,
+   QEMUClkRateUpdateCallback *cb,
+   void *opaque)
+{
+clk->cb = cb;
+clk->opaque = opaque;
+}
+
 void qemu_clk_device_add_clock(DeviceState *dev, QEMUClock *clk,

[Qemu-devel] [PATCH v3 05/10] qdev-monitor: print the device's clock with info qtree

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This prints the clock attached to a DeviceState when using "info qtree" monitor
command.

For example:

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
gpio-out "RST_A9" 4
qemu-clk "dbg_trace" 0.0
qemu-clk "vpll_to_lpd" 1250.0
qemu-clk "dp_stc_ref" 0.0
qemu-clk "dpll_to_lpd" 1250.0
qemu-clk "acpu_clk" 0.0
qemu-clk "pcie_ref" 0.0
qemu-clk "topsw_main" 0.0
qemu-clk "topsw_lsbus" 0.0
qemu-clk "dp_audio_ref" 0.0
qemu-clk "sata_ref" 0.0
qemu-clk "dp_video_ref" 1428571.4
qemu-clk "vpll_clk" 5000.0
qemu-clk "apll_to_lpd" 1250.0
qemu-clk "dpll_clk" 5000.0
qemu-clk "gpu_ref" 0.0
qemu-clk "aux_refclk" 0.0
qemu-clk "video_clk" 2700.0
qemu-clk "gdma_ref" 0.0
qemu-clk "gt_crx_ref_clk" 0.0
qemu-clk "dbg_fdp" 0.0
qemu-clk "apll_clk" 5000.0
qemu-clk "pss_alt_ref_clk" 0.0
qemu-clk "ddr" 0.0
qemu-clk "pss_ref_clk" 5000.0
qemu-clk "dpdma_ref" 0.0
qemu-clk "dbg_tstmp" 0.0
mmio fd1a/010c

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h |  9 +
 qdev-monitor.c|  2 ++
 qemu-clock.c  | 28 
 3 files changed, 39 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 1c57df4..8f0daa8 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -149,4 +149,13 @@ void qemu_clk_set_callback(QEMUClock *clk,
QEMUClkRateUpdateCallback *cb,
void *opaque);
 
+/**
+ * qemu_clk_print:
+ * @dev: the device for which the clock need to be printed.
+ *
+ * Print the clock information for a given device.
+ *
+ */
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 549f45f..02f8255 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -30,6 +30,7 @@
 #include "qemu/help_option.h"
 #include "sysemu/block-backend.h"
 #include "migration/migration.h"
+#include "qemu/qemu-clock.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -699,6 +700,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int 
indent)
 ngl->num_out);
 }
 }
+qemu_clk_print(mon, dev, indent);
 class = object_get_class(OBJECT(dev));
 do {
 qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
diff --git a/qemu-clock.c b/qemu-clock.c
index 8f342f6..d5dd928 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -27,6 +27,7 @@
 #include "qemu/log.h"
 #include "qapi/error.h"
 #include "hw/qdev-core.h"
+#include "monitor/monitor.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -134,6 +135,33 @@ QEMUClock *qemu_clk_device_get_clock(DeviceState *dev, 
const char *name)
 return QEMU_CLOCK(clk);
 }
 
+struct print_opaque {
+Monitor *mon;
+int indent;
+};
+
+static int qemu_clk_print_rec(Object *obj, void *opaque)
+{
+QEMUClock *clk = (QEMUClock *)(object_dynamic_cast(obj, TYPE_CLOCK));
+struct print_opaque *po = opaque;
+
+if (clk) {
+monitor_printf(po->mon, "%*s" "qemu-clk \"%s\" %" PRIu64 "\n",
+   po->indent, " ", clk->name, clk->rate);
+}
+
+return 0;
+}
+
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent)
+{
+struct print_opaque po;
+
+po.indent = indent;
+po.mon = mon;
+object_child_foreach(OBJECT(dev), qemu_clk_print_rec, &po);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 02/10] qemu-clk: allow to add a clock to a device

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This allows to add a clock to a DeviceState.
Contrary to gpios, the clock pins are not contained in the DeviceState but
with the child property so they can appears in the qom-tree.

Signed-off-by: KONRAD Frederic 

V2 -> V3:
  * s/qemu_clk/QEMUClock/g
V1 -> V2:
  * Rename the function use 'add' instead of 'attach'
---
 include/qemu/qemu-clock.h | 24 +++-
 qemu-clock.c  | 23 +++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 446a490..ffe743d 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -33,8 +33,30 @@
 typedef struct QEMUClock {
 /*< private >*/
 Object parent_obj;
+char *name;/* name of this clock in the device. */
 } QEMUClock;
 
-#endif /* QEMU_CLOCK_H */
+/**
+ * qemu_clk_device_add_clock:
+ * @dev: the device on which the clock needs to be added.
+ * @clk: the clock which needs to be added.
+ * @name: the name of the clock can't be NULL.
+ *
+ * Add @clk to device @dev as a clock named @name.
+ *
+ */
+void qemu_clk_device_add_clock(DeviceState *dev, QEMUClock *clk,
+   const char *name);
 
+/**
+ * qemu_clk_device_get_clock:
+ * @dev: the device which contains the clock.
+ * @name: the name of the clock.
+ *
+ * Get the clock named @name contained in the device @dev, or NULL if not 
found.
+ *
+ * Returns the clock named @name contained in @dev.
+ */
+QEMUClock *qemu_clk_device_get_clock(DeviceState *dev, const char *name);
 
+#endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index 3bef144..6eeecf3 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -25,6 +25,7 @@
 #include "qemu/qemu-clock.h"
 #include "hw/hw.h"
 #include "qemu/log.h"
+#include "qapi/error.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -36,6 +37,28 @@
 }\
 } while (0);
 
+void qemu_clk_device_add_clock(DeviceState *dev, QEMUClock *clk,
+   const char *name)
+{
+assert(name);
+assert(!clk->name);
+object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort);
+clk->name = g_strdup(name);
+}
+
+QEMUClock *qemu_clk_device_get_clock(DeviceState *dev, const char *name)
+{
+gchar *path = NULL;
+Object *clk;
+bool ambiguous;
+
+path = g_strdup_printf("%s/%s", object_get_canonical_path(OBJECT(dev)),
+   name);
+clk = object_resolve_path(path, &ambiguous);
+g_free(path);
+return QEMU_CLOCK(clk);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 06/10] docs: add qemu-clock documentation

2017-02-28 Thread fred . konrad
From: KONRAD Frederic 

This adds the qemu-clock documentation.

Signed-off-by: KONRAD Frederic 

V1 -> V2:
  * Fixed in accordance with the changes in the previous patches.
---
 docs/clock.txt | 278 +
 1 file changed, 278 insertions(+)
 create mode 100644 docs/clock.txt

diff --git a/docs/clock.txt b/docs/clock.txt
new file mode 100644
index 000..010ae50
--- /dev/null
+++ b/docs/clock.txt
@@ -0,0 +1,278 @@
+
+What is a QEMU_CLOCK
+
+
+A QEMU_CLOCK is a QOM Object developed for the purpose of modeling a clock tree
+with QEMU.
+
+It only simulates the clock by keeping a copy of the current frequency and
+doesn't model the signal itself such as pin toggle or duty cycle.
+
+It allows to model the impact of badly configured PLL, clock source selection
+or disabled clock on the models.
+
+Binding the clock together to create a tree
+===
+
+In order to create a clock tree with QEMU_CLOCK two or more clock must be bound
+together. Let's say there are two clocks clk_a and clk_b:
+Using qemu_clk_bind(clk_a, clk_b) will bind clk_a and clk_b.
+
+Binding two qemu-clk together creates a unidirectional link which means that
+changing the rate of clk_a will propagate to clk_b and not the opposite.
+The binding process automatically refreshes clk_b rate.
+
+Clock can be bound and unbound during execution for modeling eg: a clock
+selector.
+
+A clock can drive more than one other clock. eg with this code:
+qemu_clk_bind(clk_a, clk_b);
+qemu_clk_bind(clk_a, clk_c);
+
+A clock rate change one clk_a will propagate to clk_b and clk_c.
+
+Implementing a callback on a rate change
+
+
+The function prototype is the following:
+typedef uint64_t QEMUClkRateUpdateCallback(void *opaque, uint64_t rate);
+
+It's main goal is to modify the rate before it's passed to the next clocks in
+the tree.
+
+eg: for a 4x PLL the function will be:
+uint64_t qemu_clk_rate_change_cb(void *opaque, uint64_t rate)
+{
+return 4 * rate;
+}
+
+To set the callback for the clock:
+void qemu_clk_set_callback(qemu_clk clk, QEMUClkRateUpdateCallback *cb,
+   void *opaque);
+can be called.
+
+The rate update process
+===
+
+The rate update happen in this way:
+When a model wants to update a clock frequency (eg: based on a register change
+or something similar) it will call qemu_clk_update_rate(..) on the clock:
+  * The callback associated to the clock is called with the new rate.
+  * qemu_clk_update_rate(..) is then called on all bound clocks with the value
+returned by the callback.
+
+NOTE: When no callback is attached, the clock qemu_clk_update_rate(..) is 
called
+on the next clock in the tree with the rate unmodified.
+
+Adding a QEMU_CLOCK to a DeviceState
+
+
+Adding a qemu-clk to a DeviceState is required to be able to get the clock
+outside the model through qemu_clk_device_get_clock(..).
+
+It is also required to be able to print the clock and its rate with info qtree.
+For example:
+
+  type System
+  dev: xlnx.zynqmp_crf, id ""
+gpio-out "sysbus-irq" 1
+gpio-out "RST_A9" 4
+qemu-clk "dbg_trace" 0
+qemu-clk "vpll_to_lpd" 62500
+qemu-clk "dp_stc_ref" 0
+qemu-clk "dpll_to_lpd" 1250
+qemu-clk "acpu_clk" 0
+qemu-clk "pcie_ref" 0
+qemu-clk "topsw_main" 0
+qemu-clk "topsw_lsbus" 0
+qemu-clk "dp_audio_ref" 0
+qemu-clk "sata_ref" 0
+qemu-clk "dp_video_ref" 71428568
+qemu-clk "vpll_clk" 25
+qemu-clk "apll_to_lpd" 1250
+qemu-clk "dpll_clk" 5000
+qemu-clk "gpu_ref" 0
+qemu-clk "aux_refclk" 0
+qemu-clk "video_clk" 2700
+qemu-clk "gdma_ref" 0
+qemu-clk "gt_crx_ref_clk" 0
+qemu-clk "dbg_fdp" 0
+qemu-clk "apll_clk" 5000
+qemu-clk "pss_alt_ref_clk" 0
+qemu-clk "ddr" 0
+qemu-clk "pss_ref_clk" 5000
+qemu-clk "dpdma_ref" 0
+qemu-clk "dbg_tstmp" 0
+mmio fd1a/010c
+
+This way a DeviceState can have multiple clock input or output.
+
+Examples
+
+
+Those are the different way of using the QEMUClock object.
+
+Modelling a fixed clock generator
+=
+
+Here is a brief example of a device acting as a clock source:
+
+typedef struct {
+DeviceState parent_obj;
+
+uint32_t rate;
+QEMUClock out;
+} FixedClock;
+
+During the initialization the device must initialize its clock object:
+
+static void fixed_clock_instance_init(Object *obj)
+{
+FixedClock *s = FIXED_CLOCK(obj);
+
+object_initialize(&s->out, sizeof(s->out), TYPE_CLOCK);
+qemu_clk_device_add_clock(DEVICE(obj), &s->out, "clk_out");
+}
+
+As the device acts as a clock source it must refresh the clock tree during the
+realize phase:
+
+static void fixed_clock_realizefn(DeviceState *dev, Error **errp)
+{
+FixedClock *s = FIXED_CLOCK(dev);
+

[Qemu-devel] [PATCH V2 0/7] execute code from mmio area

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

This series allows to execute code from mmio areas.
The main goal of this is to be able to run code for example from an SPI device.

The three first patch fixes the way get_page_addr_code fills the TLB.

The fourth patch implements the mmio execution helpers: the device must
implement the request_ptr callback of the MemoryRegion and will be notified when
the guest wants to execute code from it.

The fifth patch introduces mmio_interface device which allows to dynamically
map a host pointer somewhere into the memory.

The sixth patch implements the execution from the SPI memories in the
xilinx_spips model.

Thanks,
Fred

V1 -> V2:
  * Fix the DPRINTF error.
RFC -> V1:
  * Use an interface (mmio-interface) to fix any reference leak issue.

KONRAD Frederic (7):
  cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT
  cputlb: move get_page_addr_code
  cputlb: fix the way get_page_addr_code fills the tlb
  exec: allow to get a pointer for some mmio memory region
  qdev: add MemoryRegion property
  introduce mmio_interface
  xilinx_spips: allow mmio execution

 cputlb.c |  81 ++---
 hw/misc/Makefile.objs|   1 +
 hw/misc/mmio_interface.c | 128 +++
 hw/ssi/xilinx_spips.c|  74 --
 include/exec/memory.h|  35 +++
 include/hw/misc/mmio_interface.h |  49 +++
 include/hw/qdev-properties.h |   2 +
 memory.c |  57 +
 8 files changed, 372 insertions(+), 55 deletions(-)
 create mode 100644 hw/misc/mmio_interface.c
 create mode 100644 include/hw/misc/mmio_interface.h

-- 
1.8.3.1




[Qemu-devel] [PATCH V2 6/7] introduce mmio_interface

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

This introduces mmio_interface object which contains a MemoryRegion
and can be hotplugged/hotunplugged.

Signed-off-by: KONRAD Frederic 

V1 -> V2:
  * Fix the qemu_log format.
---
 hw/misc/Makefile.objs|   1 +
 hw/misc/mmio_interface.c | 128 +++
 include/hw/misc/mmio_interface.h |  49 +++
 3 files changed, 178 insertions(+)
 create mode 100644 hw/misc/mmio_interface.c
 create mode 100644 include/hw/misc/mmio_interface.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 898e4cc..91580a3 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -55,3 +55,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-y += mmio_interface.o
\ No newline at end of file
diff --git a/hw/misc/mmio_interface.c b/hw/misc/mmio_interface.c
new file mode 100644
index 000..6f004d2
--- /dev/null
+++ b/hw/misc/mmio_interface.c
@@ -0,0 +1,128 @@
+/*
+ * mmio_interface.c
+ *
+ *  Copyright (C) 2017 : GreenSocs
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option)any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/mmio_interface.h"
+#include "qapi/error.h"
+
+#ifndef DEBUG_MMIO_INTERFACE
+#define DEBUG_MMIO_INTERFACE 0
+#endif
+
+static uint64_t mmio_interface_counter;
+
+#define DPRINTF(fmt, ...) do { 
\
+if (DEBUG_MMIO_INTERFACE) {
\
+qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## 
__VA_ARGS__);\
+}  
\
+} while (0);
+
+static void mmio_interface_init(Object *obj)
+{
+MMIOInterface *s = MMIO_INTERFACE(obj);
+
+if (DEBUG_MMIO_INTERFACE) {
+s->id = mmio_interface_counter++;
+}
+
+DPRINTF("interface created\n");
+s->host_ptr = 0;
+s->subregion = 0;
+}
+
+static void mmio_interface_realize(DeviceState *dev, Error **errp)
+{
+MMIOInterface *s = MMIO_INTERFACE(dev);
+
+DPRINTF("realize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+
+if (!s->host_ptr) {
+error_setg(errp, "host_ptr property must be set");
+}
+
+if (!s->subregion) {
+error_setg(errp, "subregion property must be set");
+}
+
+memory_region_init_ram_ptr(&s->ram_mem, OBJECT(s), "ram",
+   s->end - s->start + 1, s->host_ptr);
+memory_region_set_readonly(&s->ram_mem, s->ro);
+memory_region_add_subregion(s->subregion, s->start, &s->ram_mem);
+}
+
+static void mmio_interface_unrealize(DeviceState *dev, Error **errp)
+{
+MMIOInterface *s = MMIO_INTERFACE(dev);
+
+DPRINTF("unrealize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+memory_region_del_subregion(s->subregion, &s->ram_mem);
+}
+
+static void mmio_interface_finalize(Object *obj)
+{
+MMIOInterface *s = MMIO_INTERFACE(obj);
+
+DPRINTF("finalize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+object_unparent(OBJECT(&s->ram_mem));
+}
+
+static Property mmio_interface_properties[] = {
+DEFINE_PROP_UINT64("start", MMIOInterface, start, 0),
+DEFINE_PROP_UINT64("end", MMIOInterface, end, 0),
+DEFINE_PROP_PTR("host_ptr", MMIOInterface, host_ptr),
+DEFINE_PROP_BOOL("ro", MMIOInterface, ro, false),
+DEFINE_PROP_MEMORY_REGION("subregion", MMIOInterface, subregion),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mmio_interface_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = mmio_interface_realize;
+dc->unrealize = mmio_interface_unrealize;
+dc->props = mmio_interface_properties;
+}
+
+static const TypeInfo mmio_interface_info = {
+.name  = TYPE_MMIO_INTERFACE,
+.parent= TYPE_DEVICE,
+.instance_size = sizeof(MMIOInterface),
+.instance_init = mmio_interface_init,
+.instance_finalize = mmio_int

[Qemu-devel] [PATCH V2 1/7] cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

This replaces env1 and page_index variables by env and index
so we can use VICTIM_TLB_HIT macro later.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 6c39927..665caea 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -457,21 +457,21 @@ static void report_bad_exec(CPUState *cpu, target_ulong 
addr)
  * is actually a ram_addr_t (in system mode; the user mode emulation
  * version of this function returns a guest virtual address).
  */
-tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
 {
-int mmu_idx, page_index, pd;
+int mmu_idx, index, pd;
 void *p;
 MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env1);
+CPUState *cpu = ENV_GET_CPU(env);
 CPUIOTLBEntry *iotlbentry;
 
-page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env1, true);
-if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
  (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env1, addr);
+cpu_ldub_code(env, addr);
 }
-iotlbentry = &env1->iotlb[mmu_idx][page_index];
+iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
 mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
 if (memory_region_is_unassigned(mr)) {
@@ -484,7 +484,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, 
target_ulong addr)
 exit(1);
 }
 }
-p = (void *)((uintptr_t)addr + 
env1->tlb_table[mmu_idx][page_index].addend);
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
 return qemu_ram_addr_from_host_nofail(p);
 }
 
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 5/7] qdev: add MemoryRegion property

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

We need to pass a pointer to a MemoryRegion for mmio_interface.
So this just adds that.

Signed-off-by: KONRAD Frederic 
---
 include/hw/qdev-properties.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 7ac3153..babb258 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -171,6 +171,8 @@ extern PropertyInfo qdev_prop_arraylen;
 DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
 #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
 DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+#define DEFINE_PROP_MEMORY_REGION(_n, _s, _f) \
+DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, MemoryRegion *)
 
 #define DEFINE_PROP_END_OF_LIST()   \
 {}
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 7/7] xilinx_spips: allow mmio execution

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

This allows to execute from the lqspi area.

When the request_ptr is called the device loads 1024bytes from the SPI device.
Then this code can be executed by the guest.

Signed-off-by: KONRAD Frederic 
---
 hw/ssi/xilinx_spips.c | 74 ++-
 1 file changed, 55 insertions(+), 19 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index da8adfa..e833028 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -496,6 +496,18 @@ static const MemoryRegionOps spips_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
+{
+XilinxSPIPS *s = &q->parent_obj;
+
+if (q->lqspi_cached_addr != ~0ULL) {
+/* Invalidate the current mapped mmio */
+memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
+  LQSPI_CACHE_SIZE);
+q->lqspi_cached_addr = ~0ULL;
+}
+}
+
 static void xilinx_qspips_write(void *opaque, hwaddr addr,
 uint64_t value, unsigned size)
 {
@@ -505,7 +517,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
 addr >>= 2;
 
 if (addr == R_LQSPI_CFG) {
-q->lqspi_cached_addr = ~0ULL;
+xilinx_qspips_invalidate_mmio_ptr(q);
 }
 }
 
@@ -517,27 +529,20 @@ static const MemoryRegionOps qspips_ops = {
 
 #define LQSPI_CACHE_SIZE 1024
 
-static uint64_t
-lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+static void lqspi_load_cache(void *opaque, hwaddr addr)
 {
-int i;
 XilinxQSPIPS *q = opaque;
 XilinxSPIPS *s = opaque;
-uint32_t ret;
-
-if (addr >= q->lqspi_cached_addr &&
-addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
-ret = cpu_to_le32(*(uint32_t *)retp);
-DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
-   (unsigned)ret);
-return ret;
-} else {
-int flash_addr = (addr / num_effective_busses(s));
-int slave = flash_addr >> LQSPI_ADDRESS_BITS;
-int cache_entry = 0;
-uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
-
+int i;
+int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
+   / num_effective_busses(s));
+int slave = flash_addr >> LQSPI_ADDRESS_BITS;
+int cache_entry = 0;
+uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
+
+if (addr < q->lqspi_cached_addr ||
+addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+xilinx_qspips_invalidate_mmio_ptr(q);
 s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
 s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
 
@@ -589,12 +594,43 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 xilinx_spips_update_cs_lines(s);
 
 q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
+}
+}
+
+static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
+unsigned *offset)
+{
+XilinxQSPIPS *q = opaque;
+hwaddr offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
+
+lqspi_load_cache(opaque, offset_within_the_region);
+*size = LQSPI_CACHE_SIZE;
+*offset = offset_within_the_region;
+return q->lqspi_buf;
+}
+
+static uint64_t
+lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+{
+XilinxQSPIPS *q = opaque;
+uint32_t ret;
+
+if (addr >= q->lqspi_cached_addr &&
+addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
+ret = cpu_to_le32(*(uint32_t *)retp);
+DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
+   (unsigned)ret);
+return ret;
+} else {
+lqspi_load_cache(opaque, addr);
 return lqspi_read(opaque, addr, size);
 }
 }
 
 static const MemoryRegionOps lqspi_ops = {
 .read = lqspi_read,
+.request_ptr = lqspi_request_mmio_ptr,
 .endianness = DEVICE_NATIVE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 3/7] cputlb: fix the way get_page_addr_code fills the tlb

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

get_page_addr_code(..) does a cpu_ldub_code to fill the tlb:
This can lead to some side effects if a device is mapped at this address.

So this patch replaces the cpu_memory_ld by a tlb_fill.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index b3a5f47..846341e 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -534,8 +534,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 mmu_idx = cpu_mmu_index(env, true);
 if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
+ (addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK {
+if (!VICTIM_TLB_HIT(addr_read, addr)) {
+tlb_fill(ENV_GET_CPU(env), addr, MMU_INST_FETCH, mmu_idx, 0);
+}
 }
 iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 4/7] exec: allow to get a pointer for some mmio memory region

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

This introduces a special callback which allows to run code from some MMIO
devices.

SysBusDevice with a MemoryRegion which implements the request_ptr callback will
be notified when the guest try to execute code from their offset. Then it will
be able to eg: pre-load some code from an SPI device or ask a pointer from an
external simulator, etc..

When the pointer or the data in it are no longer valid the device has to
invalidate it.

Signed-off-by: KONRAD Frederic 

RFC -> V1:
  * Use mmio-interface instead of directly creating the subregion.
---
 cputlb.c  |  7 +++
 include/exec/memory.h | 35 +++
 memory.c  | 57 +++
 3 files changed, 99 insertions(+)

diff --git a/cputlb.c b/cputlb.c
index 846341e..9077247 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -545,6 +545,13 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 if (memory_region_is_unassigned(mr)) {
 CPUClass *cc = CPU_GET_CLASS(cpu);
 
+if (memory_region_request_mmio_ptr(mr, addr)) {
+/* A MemoryRegion is potentially added so re-run the
+ * get_page_addr_code.
+ */
+return get_page_addr_code(env, addr);
+}
+
 if (cc->do_unassigned_access) {
 cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
 } else {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 987f925..36b0eec 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -120,6 +120,15 @@ struct MemoryRegionOps {
 uint64_t data,
 unsigned size,
 MemTxAttrs attrs);
+/* Instruction execution pre-callback:
+ * @addr is the address of the access relative to the @mr.
+ * @size is the size of the area returned by the callback.
+ * @offset is the location of the pointer inside @mr.
+ *
+ * Returns a pointer to a location which contains guest code.
+ */
+void *(*request_ptr)(void *opaque, hwaddr addr, unsigned *size,
+ unsigned *offset);
 
 enum device_endian endianness;
 /* Guest-visible constraints: */
@@ -1253,6 +1262,32 @@ void memory_global_dirty_log_stop(void);
 void mtree_info(fprintf_function mon_printf, void *f, bool flatview);
 
 /**
+ * memory_region_request_mmio_ptr: request a pointer to an mmio
+ * MemoryRegion. If it is possible map a RAM MemoryRegion with this pointer.
+ * When the device wants to invalidate the pointer it will call
+ * memory_region_invalidate_mmio_ptr.
+ *
+ * @mr: #MemoryRegion to check
+ * @addr: address within that region
+ *
+ * Returns true on success, false otherwise.
+ */
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr);
+
+/**
+ * memory_region_invalidate_mmio_ptr: invalidate the pointer to an mmio
+ * previously requested.
+ * In the end that means that if something wants to execute from this area it
+ * will need to request the pointer again.
+ *
+ * @mr: #MemoryRegion associated to the pointer.
+ * @addr: address within that region
+ * @size: size of that area.
+ */
+void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
+   unsigned size);
+
+/**
  * memory_region_dispatch_read: perform a read directly to the specified
  * MemoryRegion.
  *
diff --git a/memory.c b/memory.c
index 6c58373..a605250 100644
--- a/memory.c
+++ b/memory.c
@@ -30,6 +30,8 @@
 #include "exec/ram_addr.h"
 #include "sysemu/kvm.h"
 #include "sysemu/sysemu.h"
+#include "hw/misc/mmio_interface.h"
+#include "hw/qdev-properties.h"
 
 //#define DEBUG_UNASSIGNED
 
@@ -2375,6 +2377,61 @@ void memory_listener_unregister(MemoryListener *listener)
 QTAILQ_REMOVE(&listener->address_space->listeners, listener, link_as);
 }
 
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr)
+{
+void *host;
+unsigned size = 0;
+unsigned offset = 0;
+Object *new_interface;
+
+if (!mr || !mr->ops->request_ptr) {
+return false;
+}
+
+/*
+ * Avoid an update if the request_ptr call
+ * memory_region_invalidate_mmio_ptr which seems to be likely when we use
+ * a cache.
+ */
+memory_region_transaction_begin();
+
+host = mr->ops->request_ptr(mr->opaque, addr - mr->addr, &size, &offset);
+
+if (!host || !size) {
+memory_region_transaction_commit();
+return false;
+}
+
+new_interface = object_new("mmio_interface");
+qdev_prop_set_uint64(DEVICE(new_interface), "start", offset);
+qdev_prop_set_uint64(DEVICE(new_interface), "end", offset + size - 1);
+qdev_prop_set_bit(DEVICE(new_interface), "ro", true);
+qdev_prop_set_ptr(DEVICE(new_interface), "host_ptr", host);
+qdev_prop_set_ptr(DEVICE(new_interface), "subregion", mr);
+object_property_set_bool(OBJECT(new_interface), true, "realize

[Qemu-devel] [PATCH V2 2/7] cputlb: move get_page_addr_code

2017-02-17 Thread fred . konrad
From: KONRAD Frederic 

This just moves the code before VICTIM_TLB_HIT macro definition
so we can use it.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 72 
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 665caea..b3a5f47 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -452,42 +452,6 @@ static void report_bad_exec(CPUState *cpu, target_ulong 
addr)
 log_cpu_state_mask(LOG_GUEST_ERROR, cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
 }
 
-/* NOTE: this function can trigger an exception */
-/* NOTE2: the returned address is not exactly the physical address: it
- * is actually a ram_addr_t (in system mode; the user mode emulation
- * version of this function returns a guest virtual address).
- */
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
-{
-int mmu_idx, index, pd;
-void *p;
-MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env);
-CPUIOTLBEntry *iotlbentry;
-
-index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env, true);
-if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
-}
-iotlbentry = &env->iotlb[mmu_idx][index];
-pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
-if (memory_region_is_unassigned(mr)) {
-CPUClass *cc = CPU_GET_CLASS(cpu);
-
-if (cc->do_unassigned_access) {
-cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
-} else {
-report_bad_exec(cpu, addr);
-exit(1);
-}
-}
-p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
-return qemu_ram_addr_from_host_nofail(p);
-}
-
 static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
  target_ulong addr, uintptr_t retaddr, int size)
 {
@@ -554,6 +518,42 @@ static bool victim_tlb_hit(CPUArchState *env, size_t 
mmu_idx, size_t index,
   victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
  (ADDR) & TARGET_PAGE_MASK)
 
+/* NOTE: this function can trigger an exception */
+/* NOTE2: the returned address is not exactly the physical address: it
+ * is actually a ram_addr_t (in system mode; the user mode emulation
+ * version of this function returns a guest virtual address).
+ */
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
+{
+int mmu_idx, index, pd;
+void *p;
+MemoryRegion *mr;
+CPUState *cpu = ENV_GET_CPU(env);
+CPUIOTLBEntry *iotlbentry;
+
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
+ (addr & TARGET_PAGE_MASK))) {
+cpu_ldub_code(env, addr);
+}
+iotlbentry = &env->iotlb[mmu_idx][index];
+pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
+mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
+if (memory_region_is_unassigned(mr)) {
+CPUClass *cc = CPU_GET_CLASS(cpu);
+
+if (cc->do_unassigned_access) {
+cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
+} else {
+report_bad_exec(cpu, addr);
+exit(1);
+}
+}
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
+return qemu_ram_addr_from_host_nofail(p);
+}
+
 /* Probe for whether the specified guest write access is permitted.
  * If it is not permitted then an exception will be taken in the same
  * way as if this were a real write access (and we will not return).
-- 
1.8.3.1




[Qemu-devel] [PATCH V1 1/7] cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

This replaces env1 and page_index variables by env and index
so we can use VICTIM_TLB_HIT macro later.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 6c39927..665caea 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -457,21 +457,21 @@ static void report_bad_exec(CPUState *cpu, target_ulong 
addr)
  * is actually a ram_addr_t (in system mode; the user mode emulation
  * version of this function returns a guest virtual address).
  */
-tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
 {
-int mmu_idx, page_index, pd;
+int mmu_idx, index, pd;
 void *p;
 MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env1);
+CPUState *cpu = ENV_GET_CPU(env);
 CPUIOTLBEntry *iotlbentry;
 
-page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env1, true);
-if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
  (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env1, addr);
+cpu_ldub_code(env, addr);
 }
-iotlbentry = &env1->iotlb[mmu_idx][page_index];
+iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
 mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
 if (memory_region_is_unassigned(mr)) {
@@ -484,7 +484,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, 
target_ulong addr)
 exit(1);
 }
 }
-p = (void *)((uintptr_t)addr + 
env1->tlb_table[mmu_idx][page_index].addend);
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
 return qemu_ram_addr_from_host_nofail(p);
 }
 
-- 
1.8.3.1




[Qemu-devel] [PATCH V1 0/7] execute code from mmio area

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

This series allows to execute code from mmio areas.
The main goal of this is to be able to run code for example from an SPI device.

The three first patch fixes the way get_page_addr_code fills the TLB.

The fourth patch implements the mmio execution helpers: the device must
implement the request_ptr callback of the MemoryRegion and will be notified when
the guest wants to execute code from it.

The fifth patch introduces mmio_interface device which allows to dynamically
map a host pointer somewhere into the memory.

The sixth patch implements the execution from the SPI memories in the
xilinx_spips model.

Thanks,
Fred

RFC -> V1:
  * Use an interface (mmio-interface) to fix any reference leak issue.

KONRAD Frederic (7):
  cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT
  cputlb: move get_page_addr_code
  cputlb: fix the way get_page_addr_code fills the tlb
  exec: allow to get a pointer for some mmio memory region
  qdev: add MemoryRegion property
  introduce mmio_interface
  xilinx_spips: allow mmio execution

 cputlb.c |  81 ++---
 hw/misc/Makefile.objs|   1 +
 hw/misc/mmio_interface.c | 128 +++
 hw/ssi/xilinx_spips.c|  74 --
 include/exec/memory.h|  35 +++
 include/hw/misc/mmio_interface.h |  49 +++
 include/hw/qdev-properties.h |   2 +
 memory.c |  57 +
 8 files changed, 372 insertions(+), 55 deletions(-)
 create mode 100644 hw/misc/mmio_interface.c
 create mode 100644 include/hw/misc/mmio_interface.h

-- 
1.8.3.1




[Qemu-devel] [PATCH V1 6/7] introduce mmio_interface

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

This introduces mmio_interface object which contains a MemoryRegion
and can be hotplugged/hotunplugged.

Signed-off-by: KONRAD Frederic 
---
 hw/misc/Makefile.objs|   1 +
 hw/misc/mmio_interface.c | 128 +++
 include/hw/misc/mmio_interface.h |  49 +++
 3 files changed, 178 insertions(+)
 create mode 100644 hw/misc/mmio_interface.c
 create mode 100644 include/hw/misc/mmio_interface.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 898e4cc..91580a3 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -55,3 +55,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-y += mmio_interface.o
\ No newline at end of file
diff --git a/hw/misc/mmio_interface.c b/hw/misc/mmio_interface.c
new file mode 100644
index 000..223b9cf
--- /dev/null
+++ b/hw/misc/mmio_interface.c
@@ -0,0 +1,128 @@
+/*
+ * mmio_interface.c
+ *
+ *  Copyright (C) 2017 : GreenSocs
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option)any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/mmio_interface.h"
+#include "qapi/error.h"
+
+#ifndef DEBUG_MMIO_INTERFACE
+#define DEBUG_MMIO_INTERFACE 0
+#endif
+
+static uint64_t mmio_interface_counter;
+
+#define DPRINTF(fmt, ...) do { 
\
+if (DEBUG_MMIO_INTERFACE) {
\
+qemu_log("mmio_interface: 0x%16.16lX: " fmt, s->id, ## __VA_ARGS__);   
\
+}  
\
+} while (0);
+
+static void mmio_interface_init(Object *obj)
+{
+MMIOInterface *s = MMIO_INTERFACE(obj);
+
+if (DEBUG_MMIO_INTERFACE) {
+s->id = mmio_interface_counter++;
+}
+
+DPRINTF("interface created\n");
+s->host_ptr = 0;
+s->subregion = 0;
+}
+
+static void mmio_interface_realize(DeviceState *dev, Error **errp)
+{
+MMIOInterface *s = MMIO_INTERFACE(dev);
+
+DPRINTF("realize from 0x%16.16lX to 0x%16.16lX map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+
+if (!s->host_ptr) {
+error_setg(errp, "host_ptr property must be set");
+}
+
+if (!s->subregion) {
+error_setg(errp, "subregion property must be set");
+}
+
+memory_region_init_ram_ptr(&s->ram_mem, OBJECT(s), "ram",
+   s->end - s->start + 1, s->host_ptr);
+memory_region_set_readonly(&s->ram_mem, s->ro);
+memory_region_add_subregion(s->subregion, s->start, &s->ram_mem);
+}
+
+static void mmio_interface_unrealize(DeviceState *dev, Error **errp)
+{
+MMIOInterface *s = MMIO_INTERFACE(dev);
+
+DPRINTF("unrealize from 0x%16.16lX to 0x%16.16lX map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+memory_region_del_subregion(s->subregion, &s->ram_mem);
+}
+
+static void mmio_interface_finalize(Object *obj)
+{
+MMIOInterface *s = MMIO_INTERFACE(obj);
+
+DPRINTF("finalize from 0x%16.16lX to 0x%16.16lX map host pointer"
+" %p\n", s->start, s->end, s->host_ptr);
+object_unparent(OBJECT(&s->ram_mem));
+}
+
+static Property mmio_interface_properties[] = {
+DEFINE_PROP_UINT64("start", MMIOInterface, start, 0),
+DEFINE_PROP_UINT64("end", MMIOInterface, end, 0),
+DEFINE_PROP_PTR("host_ptr", MMIOInterface, host_ptr),
+DEFINE_PROP_BOOL("ro", MMIOInterface, ro, false),
+DEFINE_PROP_MEMORY_REGION("subregion", MMIOInterface, subregion),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mmio_interface_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = mmio_interface_realize;
+dc->unrealize = mmio_interface_unrealize;
+dc->props = mmio_interface_properties;
+}
+
+static const TypeInfo mmio_interface_info = {
+.name  = TYPE_MMIO_INTERFACE,
+.parent= TYPE_DEVICE,
+.instance_size = sizeof(MMIOInterface),
+.instance_init = mmio_interface_init,
+.instance_finalize = mmio_interface_finalize,
+.class_init= mmio_interface_clas

[Qemu-devel] [PATCH V1 2/7] cputlb: move get_page_addr_code

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

This just moves the code before VICTIM_TLB_HIT macro definition
so we can use it.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 72 
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 665caea..b3a5f47 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -452,42 +452,6 @@ static void report_bad_exec(CPUState *cpu, target_ulong 
addr)
 log_cpu_state_mask(LOG_GUEST_ERROR, cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
 }
 
-/* NOTE: this function can trigger an exception */
-/* NOTE2: the returned address is not exactly the physical address: it
- * is actually a ram_addr_t (in system mode; the user mode emulation
- * version of this function returns a guest virtual address).
- */
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
-{
-int mmu_idx, index, pd;
-void *p;
-MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env);
-CPUIOTLBEntry *iotlbentry;
-
-index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env, true);
-if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
-}
-iotlbentry = &env->iotlb[mmu_idx][index];
-pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
-if (memory_region_is_unassigned(mr)) {
-CPUClass *cc = CPU_GET_CLASS(cpu);
-
-if (cc->do_unassigned_access) {
-cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
-} else {
-report_bad_exec(cpu, addr);
-exit(1);
-}
-}
-p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
-return qemu_ram_addr_from_host_nofail(p);
-}
-
 static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
  target_ulong addr, uintptr_t retaddr, int size)
 {
@@ -554,6 +518,42 @@ static bool victim_tlb_hit(CPUArchState *env, size_t 
mmu_idx, size_t index,
   victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
  (ADDR) & TARGET_PAGE_MASK)
 
+/* NOTE: this function can trigger an exception */
+/* NOTE2: the returned address is not exactly the physical address: it
+ * is actually a ram_addr_t (in system mode; the user mode emulation
+ * version of this function returns a guest virtual address).
+ */
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
+{
+int mmu_idx, index, pd;
+void *p;
+MemoryRegion *mr;
+CPUState *cpu = ENV_GET_CPU(env);
+CPUIOTLBEntry *iotlbentry;
+
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
+ (addr & TARGET_PAGE_MASK))) {
+cpu_ldub_code(env, addr);
+}
+iotlbentry = &env->iotlb[mmu_idx][index];
+pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
+mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
+if (memory_region_is_unassigned(mr)) {
+CPUClass *cc = CPU_GET_CLASS(cpu);
+
+if (cc->do_unassigned_access) {
+cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
+} else {
+report_bad_exec(cpu, addr);
+exit(1);
+}
+}
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
+return qemu_ram_addr_from_host_nofail(p);
+}
+
 /* Probe for whether the specified guest write access is permitted.
  * If it is not permitted then an exception will be taken in the same
  * way as if this were a real write access (and we will not return).
-- 
1.8.3.1




[Qemu-devel] [PATCH V1 4/7] exec: allow to get a pointer for some mmio memory region

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

This introduces a special callback which allows to run code from some MMIO
devices.

SysBusDevice with a MemoryRegion which implements the request_ptr callback will
be notified when the guest try to execute code from their offset. Then it will
be able to eg: pre-load some code from an SPI device or ask a pointer from an
external simulator, etc..

When the pointer or the data in it are no longer valid the device has to
invalidate it.

Signed-off-by: KONRAD Frederic 

RFC -> V1:
  * Use mmio-interface instead of directly creating the subregion.
---
 cputlb.c  |  7 +++
 include/exec/memory.h | 35 +++
 memory.c  | 57 +++
 3 files changed, 99 insertions(+)

diff --git a/cputlb.c b/cputlb.c
index 846341e..9077247 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -545,6 +545,13 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 if (memory_region_is_unassigned(mr)) {
 CPUClass *cc = CPU_GET_CLASS(cpu);
 
+if (memory_region_request_mmio_ptr(mr, addr)) {
+/* A MemoryRegion is potentially added so re-run the
+ * get_page_addr_code.
+ */
+return get_page_addr_code(env, addr);
+}
+
 if (cc->do_unassigned_access) {
 cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
 } else {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 987f925..36b0eec 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -120,6 +120,15 @@ struct MemoryRegionOps {
 uint64_t data,
 unsigned size,
 MemTxAttrs attrs);
+/* Instruction execution pre-callback:
+ * @addr is the address of the access relative to the @mr.
+ * @size is the size of the area returned by the callback.
+ * @offset is the location of the pointer inside @mr.
+ *
+ * Returns a pointer to a location which contains guest code.
+ */
+void *(*request_ptr)(void *opaque, hwaddr addr, unsigned *size,
+ unsigned *offset);
 
 enum device_endian endianness;
 /* Guest-visible constraints: */
@@ -1253,6 +1262,32 @@ void memory_global_dirty_log_stop(void);
 void mtree_info(fprintf_function mon_printf, void *f, bool flatview);
 
 /**
+ * memory_region_request_mmio_ptr: request a pointer to an mmio
+ * MemoryRegion. If it is possible map a RAM MemoryRegion with this pointer.
+ * When the device wants to invalidate the pointer it will call
+ * memory_region_invalidate_mmio_ptr.
+ *
+ * @mr: #MemoryRegion to check
+ * @addr: address within that region
+ *
+ * Returns true on success, false otherwise.
+ */
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr);
+
+/**
+ * memory_region_invalidate_mmio_ptr: invalidate the pointer to an mmio
+ * previously requested.
+ * In the end that means that if something wants to execute from this area it
+ * will need to request the pointer again.
+ *
+ * @mr: #MemoryRegion associated to the pointer.
+ * @addr: address within that region
+ * @size: size of that area.
+ */
+void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
+   unsigned size);
+
+/**
  * memory_region_dispatch_read: perform a read directly to the specified
  * MemoryRegion.
  *
diff --git a/memory.c b/memory.c
index 6c58373..a605250 100644
--- a/memory.c
+++ b/memory.c
@@ -30,6 +30,8 @@
 #include "exec/ram_addr.h"
 #include "sysemu/kvm.h"
 #include "sysemu/sysemu.h"
+#include "hw/misc/mmio_interface.h"
+#include "hw/qdev-properties.h"
 
 //#define DEBUG_UNASSIGNED
 
@@ -2375,6 +2377,61 @@ void memory_listener_unregister(MemoryListener *listener)
 QTAILQ_REMOVE(&listener->address_space->listeners, listener, link_as);
 }
 
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr)
+{
+void *host;
+unsigned size = 0;
+unsigned offset = 0;
+Object *new_interface;
+
+if (!mr || !mr->ops->request_ptr) {
+return false;
+}
+
+/*
+ * Avoid an update if the request_ptr call
+ * memory_region_invalidate_mmio_ptr which seems to be likely when we use
+ * a cache.
+ */
+memory_region_transaction_begin();
+
+host = mr->ops->request_ptr(mr->opaque, addr - mr->addr, &size, &offset);
+
+if (!host || !size) {
+memory_region_transaction_commit();
+return false;
+}
+
+new_interface = object_new("mmio_interface");
+qdev_prop_set_uint64(DEVICE(new_interface), "start", offset);
+qdev_prop_set_uint64(DEVICE(new_interface), "end", offset + size - 1);
+qdev_prop_set_bit(DEVICE(new_interface), "ro", true);
+qdev_prop_set_ptr(DEVICE(new_interface), "host_ptr", host);
+qdev_prop_set_ptr(DEVICE(new_interface), "subregion", mr);
+object_property_set_bool(OBJECT(new_interface), true, "realize

[Qemu-devel] [PATCH V1 5/7] qdev: add MemoryRegion property

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

We need to pass a pointer to a MemoryRegion for mmio_interface.
So this just adds that.

Signed-off-by: KONRAD Frederic 
---
 include/hw/qdev-properties.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 7ac3153..babb258 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -171,6 +171,8 @@ extern PropertyInfo qdev_prop_arraylen;
 DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
 #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
 DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+#define DEFINE_PROP_MEMORY_REGION(_n, _s, _f) \
+DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, MemoryRegion *)
 
 #define DEFINE_PROP_END_OF_LIST()   \
 {}
-- 
1.8.3.1




[Qemu-devel] [PATCH V1 3/7] cputlb: fix the way get_page_addr_code fills the tlb

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

get_page_addr_code(..) does a cpu_ldub_code to fill the tlb:
This can lead to some side effects if a device is mapped at this address.

So this patch replaces the cpu_memory_ld by a tlb_fill.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index b3a5f47..846341e 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -534,8 +534,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 mmu_idx = cpu_mmu_index(env, true);
 if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
+ (addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK {
+if (!VICTIM_TLB_HIT(addr_read, addr)) {
+tlb_fill(ENV_GET_CPU(env), addr, MMU_INST_FETCH, mmu_idx, 0);
+}
 }
 iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-- 
1.8.3.1




[Qemu-devel] [PATCH V1 7/7] xilinx_spips: allow mmio execution

2017-02-16 Thread fred . konrad
From: KONRAD Frederic 

This allows to execute from the lqspi area.

When the request_ptr is called the device loads 1024bytes from the SPI device.
Then this code can be executed by the guest.

Signed-off-by: KONRAD Frederic 
---
 hw/ssi/xilinx_spips.c | 74 ++-
 1 file changed, 55 insertions(+), 19 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index da8adfa..e833028 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -496,6 +496,18 @@ static const MemoryRegionOps spips_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
+{
+XilinxSPIPS *s = &q->parent_obj;
+
+if (q->lqspi_cached_addr != ~0ULL) {
+/* Invalidate the current mapped mmio */
+memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
+  LQSPI_CACHE_SIZE);
+q->lqspi_cached_addr = ~0ULL;
+}
+}
+
 static void xilinx_qspips_write(void *opaque, hwaddr addr,
 uint64_t value, unsigned size)
 {
@@ -505,7 +517,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
 addr >>= 2;
 
 if (addr == R_LQSPI_CFG) {
-q->lqspi_cached_addr = ~0ULL;
+xilinx_qspips_invalidate_mmio_ptr(q);
 }
 }
 
@@ -517,27 +529,20 @@ static const MemoryRegionOps qspips_ops = {
 
 #define LQSPI_CACHE_SIZE 1024
 
-static uint64_t
-lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+static void lqspi_load_cache(void *opaque, hwaddr addr)
 {
-int i;
 XilinxQSPIPS *q = opaque;
 XilinxSPIPS *s = opaque;
-uint32_t ret;
-
-if (addr >= q->lqspi_cached_addr &&
-addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
-ret = cpu_to_le32(*(uint32_t *)retp);
-DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
-   (unsigned)ret);
-return ret;
-} else {
-int flash_addr = (addr / num_effective_busses(s));
-int slave = flash_addr >> LQSPI_ADDRESS_BITS;
-int cache_entry = 0;
-uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
-
+int i;
+int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
+   / num_effective_busses(s));
+int slave = flash_addr >> LQSPI_ADDRESS_BITS;
+int cache_entry = 0;
+uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
+
+if (addr < q->lqspi_cached_addr ||
+addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+xilinx_qspips_invalidate_mmio_ptr(q);
 s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
 s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
 
@@ -589,12 +594,43 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 xilinx_spips_update_cs_lines(s);
 
 q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
+}
+}
+
+static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
+unsigned *offset)
+{
+XilinxQSPIPS *q = opaque;
+hwaddr offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
+
+lqspi_load_cache(opaque, offset_within_the_region);
+*size = LQSPI_CACHE_SIZE;
+*offset = offset_within_the_region;
+return q->lqspi_buf;
+}
+
+static uint64_t
+lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+{
+XilinxQSPIPS *q = opaque;
+uint32_t ret;
+
+if (addr >= q->lqspi_cached_addr &&
+addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
+ret = cpu_to_le32(*(uint32_t *)retp);
+DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
+   (unsigned)ret);
+return ret;
+} else {
+lqspi_load_cache(opaque, addr);
 return lqspi_read(opaque, addr, size);
 }
 }
 
 static const MemoryRegionOps lqspi_ops = {
 .read = lqspi_read,
+.request_ptr = lqspi_request_mmio_ptr,
 .endianness = DEVICE_NATIVE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-- 
1.8.3.1




[Qemu-devel] [RFC 5/5] xilinx_spips: allow mmio execution

2017-02-03 Thread fred . konrad
From: KONRAD Frederic 

This allows to execute from the lqspi area.

When the request_ptr is called the device loads 1024bytes from the SPI device.
Then this code can be executed by the guest.

Signed-off-by: KONRAD Frederic 
---
 hw/ssi/xilinx_spips.c | 74 ++-
 1 file changed, 55 insertions(+), 19 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index da8adfa..e833028 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -496,6 +496,18 @@ static const MemoryRegionOps spips_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
+{
+XilinxSPIPS *s = &q->parent_obj;
+
+if (q->lqspi_cached_addr != ~0ULL) {
+/* Invalidate the current mapped mmio */
+memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
+  LQSPI_CACHE_SIZE);
+q->lqspi_cached_addr = ~0ULL;
+}
+}
+
 static void xilinx_qspips_write(void *opaque, hwaddr addr,
 uint64_t value, unsigned size)
 {
@@ -505,7 +517,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
 addr >>= 2;
 
 if (addr == R_LQSPI_CFG) {
-q->lqspi_cached_addr = ~0ULL;
+xilinx_qspips_invalidate_mmio_ptr(q);
 }
 }
 
@@ -517,27 +529,20 @@ static const MemoryRegionOps qspips_ops = {
 
 #define LQSPI_CACHE_SIZE 1024
 
-static uint64_t
-lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+static void lqspi_load_cache(void *opaque, hwaddr addr)
 {
-int i;
 XilinxQSPIPS *q = opaque;
 XilinxSPIPS *s = opaque;
-uint32_t ret;
-
-if (addr >= q->lqspi_cached_addr &&
-addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
-ret = cpu_to_le32(*(uint32_t *)retp);
-DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
-   (unsigned)ret);
-return ret;
-} else {
-int flash_addr = (addr / num_effective_busses(s));
-int slave = flash_addr >> LQSPI_ADDRESS_BITS;
-int cache_entry = 0;
-uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
-
+int i;
+int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
+   / num_effective_busses(s));
+int slave = flash_addr >> LQSPI_ADDRESS_BITS;
+int cache_entry = 0;
+uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
+
+if (addr < q->lqspi_cached_addr ||
+addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+xilinx_qspips_invalidate_mmio_ptr(q);
 s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
 s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
 
@@ -589,12 +594,43 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 xilinx_spips_update_cs_lines(s);
 
 q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
+}
+}
+
+static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
+unsigned *offset)
+{
+XilinxQSPIPS *q = opaque;
+hwaddr offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
+
+lqspi_load_cache(opaque, offset_within_the_region);
+*size = LQSPI_CACHE_SIZE;
+*offset = offset_within_the_region;
+return q->lqspi_buf;
+}
+
+static uint64_t
+lqspi_read(void *opaque, hwaddr addr, unsigned int size)
+{
+XilinxQSPIPS *q = opaque;
+uint32_t ret;
+
+if (addr >= q->lqspi_cached_addr &&
+addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
+ret = cpu_to_le32(*(uint32_t *)retp);
+DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
+   (unsigned)ret);
+return ret;
+} else {
+lqspi_load_cache(opaque, addr);
 return lqspi_read(opaque, addr, size);
 }
 }
 
 static const MemoryRegionOps lqspi_ops = {
 .read = lqspi_read,
+.request_ptr = lqspi_request_mmio_ptr,
 .endianness = DEVICE_NATIVE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-- 
1.8.3.1




[Qemu-devel] [RFC 4/5] exec: allow to get a pointer for some mmio memory region

2017-02-03 Thread fred . konrad
From: KONRAD Frederic 

This introduces a special callback which allows to run code from some MMIO
devices.

SysBusDevice with a MemoryRegion which implements the request_ptr callback will
be notified when the guest try to execute code from their offset. Then it will
be able to eg: pre-load some code from an SPI device or ask a pointer from an
external simulator, etc..

When the pointer or the data in it are no longer valid the device has to
invalidate it.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c  |  7 +++
 include/exec/memory.h | 35 +++
 memory.c  | 45 +
 3 files changed, 87 insertions(+)

diff --git a/cputlb.c b/cputlb.c
index 846341e..9077247 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -545,6 +545,13 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 if (memory_region_is_unassigned(mr)) {
 CPUClass *cc = CPU_GET_CLASS(cpu);
 
+if (memory_region_request_mmio_ptr(mr, addr)) {
+/* A MemoryRegion is potentially added so re-run the
+ * get_page_addr_code.
+ */
+return get_page_addr_code(env, addr);
+}
+
 if (cc->do_unassigned_access) {
 cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
 } else {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 987f925..36b0eec 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -120,6 +120,15 @@ struct MemoryRegionOps {
 uint64_t data,
 unsigned size,
 MemTxAttrs attrs);
+/* Instruction execution pre-callback:
+ * @addr is the address of the access relative to the @mr.
+ * @size is the size of the area returned by the callback.
+ * @offset is the location of the pointer inside @mr.
+ *
+ * Returns a pointer to a location which contains guest code.
+ */
+void *(*request_ptr)(void *opaque, hwaddr addr, unsigned *size,
+ unsigned *offset);
 
 enum device_endian endianness;
 /* Guest-visible constraints: */
@@ -1253,6 +1262,32 @@ void memory_global_dirty_log_stop(void);
 void mtree_info(fprintf_function mon_printf, void *f, bool flatview);
 
 /**
+ * memory_region_request_mmio_ptr: request a pointer to an mmio
+ * MemoryRegion. If it is possible map a RAM MemoryRegion with this pointer.
+ * When the device wants to invalidate the pointer it will call
+ * memory_region_invalidate_mmio_ptr.
+ *
+ * @mr: #MemoryRegion to check
+ * @addr: address within that region
+ *
+ * Returns true on success, false otherwise.
+ */
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr);
+
+/**
+ * memory_region_invalidate_mmio_ptr: invalidate the pointer to an mmio
+ * previously requested.
+ * In the end that means that if something wants to execute from this area it
+ * will need to request the pointer again.
+ *
+ * @mr: #MemoryRegion associated to the pointer.
+ * @addr: address within that region
+ * @size: size of that area.
+ */
+void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
+   unsigned size);
+
+/**
  * memory_region_dispatch_read: perform a read directly to the specified
  * MemoryRegion.
  *
diff --git a/memory.c b/memory.c
index 6c58373..eb3e8ec 100644
--- a/memory.c
+++ b/memory.c
@@ -2375,6 +2375,51 @@ void memory_listener_unregister(MemoryListener *listener)
 QTAILQ_REMOVE(&listener->address_space->listeners, listener, link_as);
 }
 
+bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr)
+{
+void *host;
+unsigned size = 0;
+unsigned offset = 0;
+MemoryRegion *sub;
+
+if (!mr || !mr->ops->request_ptr) {
+return false;
+}
+
+/*
+ * Avoid an update if the request_ptr call
+ * memory_region_invalidate_mmio_ptr which seems to be likely when we use
+ * a cache.
+ */
+memory_region_transaction_begin();
+
+host = mr->ops->request_ptr(mr->opaque, addr - mr->addr, &size, &offset);
+
+if (!host || !size) {
+memory_region_transaction_commit();
+return false;
+}
+
+sub = g_new(MemoryRegion, 1);
+memory_region_init_ram_ptr(sub, OBJECT(mr), "mmio-map", size, host);
+memory_region_add_subregion(mr, offset, sub);
+memory_region_transaction_commit();
+return true;
+}
+
+void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
+   unsigned size)
+{
+MemoryRegionSection section = memory_region_find(mr, offset, size);
+
+if (section.mr != mr) {
+memory_region_del_subregion(mr, section.mr);
+/* memory_region_find add a ref on section.mr */
+memory_region_unref(section.mr);
+object_unparent(OBJECT(section.mr));
+}
+}
+
 void address_space_init(AddressSpace *as, MemoryRegion *root, c

[Qemu-devel] [RFC 0/5] execute code from mmio area

2017-02-03 Thread fred . konrad
From: KONRAD Frederic 

This patch-set allows to execute code from mmio areas.
The main goal of this is to be able to run code for example from an SPI device.

The three first patch fixes the way get_page_addr_code fills the TLB.

The fourth patch implements the mmio execution helpers: the device must
implement the request_ptr callback of the MemoryRegion and will be notified when
the guest wants to execute code from it.

The fifth patch implements the execution from the SPI memories in the
xilinx_spips model.

Thanks,
Fred

KONRAD Frederic (5):
  cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT
  cputlb: move get_page_addr_code
  cputlb: fix the way get_page_addr_code fills the tlb
  exec: allow to get a pointer for some mmio memory region
  xilinx_spips: allow mmio execution

 cputlb.c  | 81 ---
 hw/ssi/xilinx_spips.c | 74 ++
 include/exec/memory.h | 35 ++
 memory.c  | 45 
 4 files changed, 180 insertions(+), 55 deletions(-)

-- 
1.8.3.1




[Qemu-devel] [RFC 2/5] cputlb: move get_page_addr_code

2017-02-03 Thread fred . konrad
From: KONRAD Frederic 

This just moves the code before VICTIM_TLB_HIT macro definition
so we can use it.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 72 
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 665caea..b3a5f47 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -452,42 +452,6 @@ static void report_bad_exec(CPUState *cpu, target_ulong 
addr)
 log_cpu_state_mask(LOG_GUEST_ERROR, cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
 }
 
-/* NOTE: this function can trigger an exception */
-/* NOTE2: the returned address is not exactly the physical address: it
- * is actually a ram_addr_t (in system mode; the user mode emulation
- * version of this function returns a guest virtual address).
- */
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
-{
-int mmu_idx, index, pd;
-void *p;
-MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env);
-CPUIOTLBEntry *iotlbentry;
-
-index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env, true);
-if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
-}
-iotlbentry = &env->iotlb[mmu_idx][index];
-pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
-if (memory_region_is_unassigned(mr)) {
-CPUClass *cc = CPU_GET_CLASS(cpu);
-
-if (cc->do_unassigned_access) {
-cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
-} else {
-report_bad_exec(cpu, addr);
-exit(1);
-}
-}
-p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
-return qemu_ram_addr_from_host_nofail(p);
-}
-
 static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
  target_ulong addr, uintptr_t retaddr, int size)
 {
@@ -554,6 +518,42 @@ static bool victim_tlb_hit(CPUArchState *env, size_t 
mmu_idx, size_t index,
   victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
  (ADDR) & TARGET_PAGE_MASK)
 
+/* NOTE: this function can trigger an exception */
+/* NOTE2: the returned address is not exactly the physical address: it
+ * is actually a ram_addr_t (in system mode; the user mode emulation
+ * version of this function returns a guest virtual address).
+ */
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
+{
+int mmu_idx, index, pd;
+void *p;
+MemoryRegion *mr;
+CPUState *cpu = ENV_GET_CPU(env);
+CPUIOTLBEntry *iotlbentry;
+
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
+ (addr & TARGET_PAGE_MASK))) {
+cpu_ldub_code(env, addr);
+}
+iotlbentry = &env->iotlb[mmu_idx][index];
+pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
+mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
+if (memory_region_is_unassigned(mr)) {
+CPUClass *cc = CPU_GET_CLASS(cpu);
+
+if (cc->do_unassigned_access) {
+cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
+} else {
+report_bad_exec(cpu, addr);
+exit(1);
+}
+}
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
+return qemu_ram_addr_from_host_nofail(p);
+}
+
 /* Probe for whether the specified guest write access is permitted.
  * If it is not permitted then an exception will be taken in the same
  * way as if this were a real write access (and we will not return).
-- 
1.8.3.1




[Qemu-devel] [RFC 3/5] cputlb: fix the way get_page_addr_code fills the tlb

2017-02-03 Thread fred . konrad
From: KONRAD Frederic 

get_page_addr_code(..) does a cpu_ldub_code to fill the tlb:
This can lead to some side effects if a device is mapped at this address.

So this patch replaces the cpu_memory_ld by a tlb_fill.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index b3a5f47..846341e 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -534,8 +534,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 mmu_idx = cpu_mmu_index(env, true);
 if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
- (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env, addr);
+ (addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK {
+if (!VICTIM_TLB_HIT(addr_read, addr)) {
+tlb_fill(ENV_GET_CPU(env), addr, MMU_INST_FETCH, mmu_idx, 0);
+}
 }
 iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
-- 
1.8.3.1




[Qemu-devel] [RFC 1/5] cputlb: cleanup get_page_addr_code to use VICTIM_TLB_HIT

2017-02-03 Thread fred . konrad
From: KONRAD Frederic 

This replaces env1 and page_index variables by env and index
so we can use VICTIM_TLB_HIT macro later.

Signed-off-by: KONRAD Frederic 
---
 cputlb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 6c39927..665caea 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -457,21 +457,21 @@ static void report_bad_exec(CPUState *cpu, target_ulong 
addr)
  * is actually a ram_addr_t (in system mode; the user mode emulation
  * version of this function returns a guest virtual address).
  */
-tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
+tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
 {
-int mmu_idx, page_index, pd;
+int mmu_idx, index, pd;
 void *p;
 MemoryRegion *mr;
-CPUState *cpu = ENV_GET_CPU(env1);
+CPUState *cpu = ENV_GET_CPU(env);
 CPUIOTLBEntry *iotlbentry;
 
-page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-mmu_idx = cpu_mmu_index(env1, true);
-if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
+index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+mmu_idx = cpu_mmu_index(env, true);
+if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
  (addr & TARGET_PAGE_MASK))) {
-cpu_ldub_code(env1, addr);
+cpu_ldub_code(env, addr);
 }
-iotlbentry = &env1->iotlb[mmu_idx][page_index];
+iotlbentry = &env->iotlb[mmu_idx][index];
 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
 mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
 if (memory_region_is_unassigned(mr)) {
@@ -484,7 +484,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, 
target_ulong addr)
 exit(1);
 }
 }
-p = (void *)((uintptr_t)addr + 
env1->tlb_table[mmu_idx][page_index].addend);
+p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
 return qemu_ram_addr_from_host_nofail(p);
 }
 
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 07/10] introduce fixed-clock

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This is a fixed clock device.
It justs behave as an empty device with a parametrable output rate.

Signed-off-by: KONRAD Frederic 
---
 hw/misc/Makefile.objs |  1 +
 hw/misc/fixed-clock.c | 88 +++
 include/hw/misc/fixed-clock.h | 30 +++
 3 files changed, 119 insertions(+)
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 include/hw/misc/fixed-clock.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 1a89615..2670c2d 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -53,3 +53,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-y += fixed-clock.o
diff --git a/hw/misc/fixed-clock.c b/hw/misc/fixed-clock.c
new file mode 100644
index 000..aa124d8
--- /dev/null
+++ b/hw/misc/fixed-clock.c
@@ -0,0 +1,88 @@
+/*
+ * Fixed clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev.h"
+#include "hw/misc/fixed-clock.h"
+#include "qemu/qemu-clock.h"
+#include "qapi/error.h"
+
+#ifndef DEBUG_FIXED_CLOCK
+#define DEBUG_FIXED_CLOCK 0
+#endif
+
+#define DPRINTF(fmt, ...) do {   \
+if (DEBUG_FIXED_CLOCK) { \
+qemu_log(__FILE__": " fmt , ## __VA_ARGS__); \
+}\
+} while (0);
+
+typedef struct {
+DeviceState parent_obj;
+
+uint32_t rate;
+struct qemu_clk out;
+} FixedClock;
+
+static Property fixed_clock_properties[] = {
+DEFINE_PROP_UINT32("rate", FixedClock, rate, 0),
+DEFINE_PROP_END_OF_LIST()
+};
+
+static void fixed_clock_realizefn(DeviceState *dev, Error **errp)
+{
+FixedClock *s = FIXED_CLOCK(dev);
+
+qemu_clk_update_rate(&s->out, s->rate);
+}
+
+static void fixed_clock_instance_init(Object *obj)
+{
+FixedClock *s = FIXED_CLOCK(obj);
+
+object_initialize(&s->out, sizeof(s->out), TYPE_CLOCK);
+qemu_clk_device_add_clock(DEVICE(obj), &s->out, "clk_out");
+}
+
+static void fixed_clock_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = fixed_clock_realizefn;
+dc->props = fixed_clock_properties;
+}
+
+static const TypeInfo fixed_clock_info = {
+.name  = TYPE_FIXED_CLOCK,
+.parent= TYPE_DEVICE,
+.instance_size = sizeof(FixedClock),
+.instance_init = fixed_clock_instance_init,
+.class_init= fixed_clock_class_init,
+};
+
+static void fixed_clock_register_types(void)
+{
+type_register_static(&fixed_clock_info);
+}
+
+type_init(fixed_clock_register_types);
diff --git a/include/hw/misc/fixed-clock.h b/include/hw/misc/fixed-clock.h
new file mode 100644
index 000..1376444
--- /dev/null
+++ b/include/hw/misc/fixed-clock.h
@@ -0,0 +1,30 @@
+/*
+ * Fixed clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef FIXED_CLOCK_H
+#define FIXED_CLOCK_H
+
+#define TYPE_FIXED_CLOCK "fixed-clock"
+#define FIXED_CLOCK(obj) OBJECT_CHECK(FixedClock, (obj), TYPE_FIXED_CLOCK)
+
+#endif /* FIXED_CLOCK_H */
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 01/10] qemu-clk: introduce qemu-clk qom object

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This introduces qemu-clk qom object.

Signed-off-by: KONRAD Frederic 
---
 Makefile.objs |  1 +
 include/qemu/qemu-clock.h | 40 +
 qemu-clock.c  | 50 +++
 3 files changed, 91 insertions(+)
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

diff --git a/Makefile.objs b/Makefile.objs
index 01cef86..de0219d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -78,6 +78,7 @@ common-obj-y += backends/
 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
 
 common-obj-$(CONFIG_FDT) += device_tree.o
+common-obj-y += qemu-clock.o
 
 ##
 # qapi
diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
new file mode 100644
index 000..e7acd68
--- /dev/null
+++ b/include/qemu/qemu-clock.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef QEMU_CLOCK_H
+#define QEMU_CLOCK_H
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+
+#define TYPE_CLOCK "qemu-clk"
+#define QEMU_CLOCK(obj) OBJECT_CHECK(struct qemu_clk, (obj), TYPE_CLOCK)
+
+typedef struct qemu_clk {
+/*< private >*/
+Object parent_obj;
+} *qemu_clk;
+
+#endif /* QEMU_CLOCK_H */
+
+
diff --git a/qemu-clock.c b/qemu-clock.c
new file mode 100644
index 000..ceea98d
--- /dev/null
+++ b/qemu-clock.c
@@ -0,0 +1,50 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/qemu-clock.h"
+#include "hw/hw.h"
+#include "qemu/log.h"
+
+#ifndef DEBUG_QEMU_CLOCK
+#define DEBUG_QEMU_CLOCK 0
+#endif
+
+#define DPRINTF(fmt, args...) do {   \
+if (DEBUG_QEMU_CLOCK) {  \
+qemu_log("%s: " fmt, __func__, ## args); \
+}\
+} while (0);
+
+static const TypeInfo qemu_clk_info = {
+.name  = TYPE_CLOCK,
+.parent= TYPE_OBJECT,
+.instance_size = sizeof(struct qemu_clk),
+};
+
+static void qemu_clk_register_types(void)
+{
+type_register_static(&qemu_clk_info);
+}
+
+type_init(qemu_clk_register_types);
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 10/10] zynqmp: add reference clock

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This adds some fixed reference clock to the zynqmp platform.
They will feed the zynqmp_crf block.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 49 
 include/hw/arm/xlnx-zynqmp.h |  6 ++
 2 files changed, 55 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 27dccdb..1bef77d 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -24,6 +24,7 @@
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
+#include "qemu/qemu-clock.h"
 
 #define GIC_NUM_SPI_INTR 160
 
@@ -182,6 +183,22 @@ static void xlnx_zynqmp_init(Object *obj)
 qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
 object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
   &error_abort);
+
+s->pss_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_ref_clk", s->pss_ref_clk,
+  &error_abort);
+object_property_set_int(s->pss_ref_clk, 5000, "rate", &error_abort);
+s->video_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "video_clk", s->video_clk, &error_abort);
+object_property_set_int(s->video_clk, 2700, "rate", &error_abort);
+s->pss_alt_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_alt_ref_clk", s->pss_alt_ref_clk,
+  &error_abort);
+s->aux_refclk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "aux_refclk", s->aux_refclk, &error_abort);
+s->gt_crx_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "gt_crx_ref_clk", s->gt_crx_ref_clk,
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -431,6 +448,38 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
+
+/* Bind the clock */
+qemu_clk_bind_clock(qemu_clk_device_get_clock(DEVICE(s->pss_ref_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "pss_ref_clk"));
+
+qemu_clk_bind_clock(qemu_clk_device_get_clock(DEVICE(s->video_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf), 
"video_clk"));
+
+qemu_clk_bind_clock(qemu_clk_device_get_clock(DEVICE(s->pss_alt_ref_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "pss_alt_ref_clk"));
+
+qemu_clk_bind_clock(qemu_clk_device_get_clock(DEVICE(s->aux_refclk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "aux_refclk"));
+
+qemu_clk_bind_clock(qemu_clk_device_get_clock(DEVICE(s->gt_crx_ref_clk),
+  "clk_out"),
+qemu_clk_device_get_clock(DEVICE(s->crf),
+  "gt_crx_ref_clk"));
+
+object_property_set_bool(s->crf, true, "realized", &err);
+object_property_set_bool(s->pss_ref_clk, true, "realized", &err);
+object_property_set_bool(s->video_clk, true, "realized", &err);
+object_property_set_bool(s->pss_alt_ref_clk, true, "realized", &err);
+object_property_set_bool(s->aux_refclk, true, "realized", &err);
+object_property_set_bool(s->gt_crx_ref_clk, true, "realized", &err);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 379a17a..d0cc57f 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -28,6 +28,7 @@
 #include "hw/ssi/xilinx_spips.h"
 #include "hw/dma/xlnx_dpdma.h"
 #include "hw/display/xlnx_dp.h"
+#include "hw/misc/fixed-clock.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
@@ -86,6 +87,11 @@ typedef struct XlnxZynqMPState {
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
+Object *pss_ref_clk;
+Object *video_clk;
+Object *pss_alt_ref_clk;
+Object *aux_refclk;
+Object *gt_crx_ref_clk;
 Object *crf;
 
 char *boot_cpu;
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 09/10] zynqmp: add the zynqmp_crf to the platform

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This adds the zynqmp_crf to the zynqmp platform.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 7 +++
 include/hw/arm/xlnx-zynqmp.h | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index bc4e66b..27dccdb 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -177,6 +177,11 @@ static void xlnx_zynqmp_init(Object *obj)
 
 object_initialize(&s->dpdma, sizeof(s->dpdma), TYPE_XLNX_DPDMA);
 qdev_set_parent_bus(DEVICE(&s->dpdma), sysbus_get_default());
+
+s->crf = object_new("xlnx.zynqmp_crf");
+qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
+object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -424,6 +429,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
  &error_abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->dpdma), 0, DPDMA_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
+
+sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index c2931bf..379a17a 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -86,6 +86,8 @@ typedef struct XlnxZynqMPState {
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
+Object *crf;
+
 char *boot_cpu;
 ARMCPU *boot_cpu_ptr;
 
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 05/10] qdev-monitor: print the device's clock with info qtree

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This prints the clock attached to a DeviceState when using "info qtree" monitor
command.

For example:

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
gpio-out "RST_A9" 4
qemu-clk "dbg_trace" 0.0
qemu-clk "vpll_to_lpd" 1250.0
qemu-clk "dp_stc_ref" 0.0
qemu-clk "dpll_to_lpd" 1250.0
qemu-clk "acpu_clk" 0.0
qemu-clk "pcie_ref" 0.0
qemu-clk "topsw_main" 0.0
qemu-clk "topsw_lsbus" 0.0
qemu-clk "dp_audio_ref" 0.0
qemu-clk "sata_ref" 0.0
qemu-clk "dp_video_ref" 1428571.4
qemu-clk "vpll_clk" 5000.0
qemu-clk "apll_to_lpd" 1250.0
qemu-clk "dpll_clk" 5000.0
qemu-clk "gpu_ref" 0.0
qemu-clk "aux_refclk" 0.0
qemu-clk "video_clk" 2700.0
qemu-clk "gdma_ref" 0.0
qemu-clk "gt_crx_ref_clk" 0.0
qemu-clk "dbg_fdp" 0.0
qemu-clk "apll_clk" 5000.0
qemu-clk "pss_alt_ref_clk" 0.0
qemu-clk "ddr" 0.0
qemu-clk "pss_ref_clk" 5000.0
qemu-clk "dpdma_ref" 0.0
qemu-clk "dbg_tstmp" 0.0
mmio fd1a/010c

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h |  9 +
 qdev-monitor.c|  2 ++
 qemu-clock.c  | 28 
 3 files changed, 39 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 45f8766..ccc381c 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -149,4 +149,13 @@ void qemu_clk_set_callback(qemu_clk clk,
QEMUClkRateUpdateCallback *cb,
void *opaque);
 
+/**
+ * qemu_clk_print:
+ * @dev: the device for which the clock need to be printed.
+ *
+ * Print the clock information for a given device.
+ *
+ */
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qdev-monitor.c b/qdev-monitor.c
index c73410c..8f6bbdf 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "qemu/help_option.h"
 #include "sysemu/block-backend.h"
+#include "qemu/qemu-clock.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -689,6 +690,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int 
indent)
 ngl->num_out);
 }
 }
+qemu_clk_print(mon, dev, indent);
 class = object_get_class(OBJECT(dev));
 do {
 qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
diff --git a/qemu-clock.c b/qemu-clock.c
index 300e38f..b34021c 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -27,6 +27,7 @@
 #include "qemu/log.h"
 #include "qapi/error.h"
 #include "hw/qdev-core.h"
+#include "monitor/monitor.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -132,6 +133,33 @@ qemu_clk qemu_clk_device_get_clock(DeviceState *dev, const 
char *name)
 return QEMU_CLOCK(clk);
 }
 
+struct print_opaque {
+Monitor *mon;
+int indent;
+};
+
+static int qemu_clk_print_rec(Object *obj, void *opaque)
+{
+qemu_clk clk = (qemu_clk)(object_dynamic_cast(obj, TYPE_CLOCK));
+struct print_opaque *po = opaque;
+
+if (clk) {
+monitor_printf(po->mon, "%*s" "qemu-clk \"%s\" %" PRIu64 "\n",
+   po->indent, " ", clk->name, clk->out_rate);
+}
+
+return 0;
+}
+
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent)
+{
+struct print_opaque po;
+
+po.indent = indent;
+po.mon = mon;
+object_child_foreach(OBJECT(dev), qemu_clk_print_rec, &po);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 06/10] docs: add qemu-clock documentation

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This adds the qemu-clock documentation.

Signed-off-by: KONRAD Frederic 

V1 -> V2:
  * Fixed in accordance with the changes in the previous patches.
---
 docs/clock.txt | 108 +
 1 file changed, 108 insertions(+)
 create mode 100644 docs/clock.txt

diff --git a/docs/clock.txt b/docs/clock.txt
new file mode 100644
index 000..aa23910
--- /dev/null
+++ b/docs/clock.txt
@@ -0,0 +1,108 @@
+
+What is a QEMU_CLOCK
+
+
+A QEMU_CLOCK is a QOM Object developed for the purpose of modeling a clock tree
+with QEMU.
+
+It only simulates the clock by keeping a copy of the current frequency and
+doesn't model the signal itself such as pin toggle or duty cycle.
+
+It allows to model the impact of badly configured PLL, clock source selection
+or disabled clock on the models.
+
+Binding the clock together to create a tree
+===
+
+In order to create a clock tree with QEMU_CLOCK two or more clock must be bound
+together. Let's say there are two clocks clk_a and clk_b:
+Using qemu_clk_bind(clk_a, clk_b) will bind clk_a and clk_b.
+
+Binding two qemu-clk together creates a unidirectional link which means that
+changing the rate of clk_a will propagate to clk_b and not the opposite.
+The binding process automatically refreshes clk_b rate.
+
+Clock can be bound and unbound during execution for modeling eg: a clock
+selector.
+
+A clock can drive more than one other clock. eg with this code:
+qemu_clk_bind(clk_a, clk_b);
+qemu_clk_bind(clk_a, clk_c);
+
+A clock rate change one clk_a will propagate to clk_b and clk_c.
+
+Implementing a callback on a rate change
+
+
+The function prototype is the following:
+typedef uint64_t QEMUClkRateUpdateCallback(void *opaque, uint64_t rate);
+
+It's main goal is to modify the rate before it's passed to the next clocks in
+the tree.
+
+eg: for a 4x PLL the function will be:
+uint64_t qemu_clk_rate_change_cb(void *opaque, uint64_t rate)
+{
+return 4 * rate;
+}
+
+To set the callback for the clock:
+void qemu_clk_set_callback(qemu_clk clk, QEMUClkRateUpdateCallback *cb,
+   void *opaque);
+can be called.
+
+The rate update process
+===
+
+The rate update happen in this way:
+When a model wants to update a clock frequency (eg: based on a register change
+or something similar) it will call qemu_clk_update_rate(..) on the clock:
+  * The callback associated to the clock is called with the new rate.
+  * qemu_clk_update_rate(..) is then called on all bound clocks with the value
+returned by the callback.
+
+NOTE: When no callback is attached, the clock qemu_clk_update_rate(..) is 
called
+with the unmodified rate.
+
+Adding a QEMU_CLOCK to a DeviceState
+
+
+Adding a qemu-clk to a DeviceState is required to be able to get the clock
+outside the model through qemu_clk_device_get_clock(..).
+
+It is also required to be able to print the clock and its rate with info qtree.
+For example:
+
+  type System
+  dev: xlnx.zynqmp_crf, id ""
+gpio-out "sysbus-irq" 1
+gpio-out "RST_A9" 4
+qemu-clk "dbg_trace" 0
+qemu-clk "vpll_to_lpd" 62500
+qemu-clk "dp_stc_ref" 0
+qemu-clk "dpll_to_lpd" 1250
+qemu-clk "acpu_clk" 0
+qemu-clk "pcie_ref" 0
+qemu-clk "topsw_main" 0
+qemu-clk "topsw_lsbus" 0
+qemu-clk "dp_audio_ref" 0
+qemu-clk "sata_ref" 0
+qemu-clk "dp_video_ref" 71428568
+qemu-clk "vpll_clk" 25
+qemu-clk "apll_to_lpd" 1250
+qemu-clk "dpll_clk" 5000
+qemu-clk "gpu_ref" 0
+qemu-clk "aux_refclk" 0
+qemu-clk "video_clk" 2700
+qemu-clk "gdma_ref" 0
+qemu-clk "gt_crx_ref_clk" 0
+qemu-clk "dbg_fdp" 0
+qemu-clk "apll_clk" 5000
+qemu-clk "pss_alt_ref_clk" 0
+qemu-clk "ddr" 0
+qemu-clk "pss_ref_clk" 5000
+qemu-clk "dpdma_ref" 0
+qemu-clk "dbg_tstmp" 0
+mmio fd1a/010c
+
+This way a DeviceState can have multiple clock input or output.
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 08/10] introduce zynqmp_crf

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This introduce Xilinx zynqmp-crf.
It is extracted from the qemu xilinx tree 
(02d2f0203dd489ed30d9c8d90c14a52c57332b25) and is used as
an example for the clock framework.
---
 hw/misc/Makefile.objs   |   1 +
 hw/misc/xilinx_zynqmp_crf.c | 968 
 2 files changed, 969 insertions(+)
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 2670c2d..60f9f4d 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -43,6 +43,7 @@ obj-$(CONFIG_RASPI) += bcm2835_property.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
+obj-$(CONFIG_ZYNQ) += xilinx_zynqmp_crf.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
diff --git a/hw/misc/xilinx_zynqmp_crf.c b/hw/misc/xilinx_zynqmp_crf.c
new file mode 100644
index 000..e4b9225
--- /dev/null
+++ b/hw/misc/xilinx_zynqmp_crf.c
@@ -0,0 +1,968 @@
+/*
+ * QEMU model of the CRF_APB APB control registers for clock controller. The
+ * RST_ctrl_fpd will be added to this as well
+ *
+ * Copyright (c) 2014 Xilinx Inc.
+ *
+ * Autogenerated by xregqemu.py 2014-01-22.
+ *
+ * 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/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/qemu-clock.h"
+
+#ifndef XILINX_CRF_APB_ERR_DEBUG
+#define XILINX_CRF_APB_ERR_DEBUG 0
+#endif
+
+#define TYPE_XILINX_CRF_APB "xlnx.zynqmp_crf"
+
+#define XILINX_CRF_APB(obj) \
+ OBJECT_CHECK(CRF_APB, (obj), TYPE_XILINX_CRF_APB)
+
+REG32(ERR_CTRL, 0x0)
+FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x4)
+FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_MASK, 0x8)
+FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_ENABLE, 0xc)
+FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_DISABLE, 0x10)
+FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(CRF_ECO, 0x18)
+REG32(APLL_CTRL, 0x20)
+FIELD(APLL_CTRL, POST_SRC, 24, 3)
+FIELD(APLL_CTRL, PRE_SRC, 20, 3)
+FIELD(APLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(APLL_CTRL, DIV2, 16, 1)
+FIELD(APLL_CTRL, FBDIV, 8, 7)
+FIELD(APLL_CTRL, BYPASS, 3, 1)
+FIELD(APLL_CTRL, RESET, 0, 1)
+REG32(APLL_CFG, 0x24)
+FIELD(APLL_CFG, LOCK_DLY, 25, 7)
+FIELD(APLL_CFG, LOCK_CNT, 13, 10)
+FIELD(APLL_CFG, LFHF, 10, 2)
+FIELD(APLL_CFG, CP, 5, 4)
+FIELD(APLL_CFG, RES, 0, 4)
+REG32(APLL_FRAC_CFG, 0x28)
+FIELD(APLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(APLL_FRAC_CFG, SEED, 22, 3)
+FIELD(APLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(APLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(APLL_FRAC_CFG, DATA, 0, 16)
+REG32(DPLL_CTRL, 0x2c)
+FIELD(DPLL_CTRL, POST_SRC, 24, 3)
+FIELD(DPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(DPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(DPLL_CTRL, DIV2, 16, 1)
+FIELD(DPLL_CTRL, FBDIV, 8, 7)
+FIELD(DPLL_CTRL, BYPASS, 3, 1)
+FIELD(DPLL_CTRL, RESET, 0, 1)
+REG32(DPLL_CFG, 0x30)
+FIELD(DPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(DPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(DPLL_CFG, LFHF, 10, 2)
+FIELD(DPLL_CFG, CP, 5, 4)
+FIELD(DPLL_CFG, RES, 0, 4)
+REG32(DPLL_FRAC_CFG, 0x34)
+FIELD(DPLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(DPLL_FRAC_CFG, SEED, 22, 3)
+FIELD(DPLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(DPLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(DPLL_FRAC_CFG, DATA, 0, 16)
+REG32(VPLL_CTRL, 0x38)
+FIELD(VPLL_CTRL, POST_SRC, 24, 3)
+FIELD(VPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(VPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(VPLL_CTRL, DIV2, 16, 1)
+FIELD(VPLL_CTRL, FBDIV, 8, 7)
+FIELD(VPLL_CTRL, BYPASS, 3, 1)
+FIELD(VPLL_CTRL, RESET, 0, 1)
+REG32(VPLL_CFG, 0x3c)
+FIELD(VPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(VPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(VPLL_CFG, LFHF, 10, 2)
+FIELD(VPLL_CFG, CP, 5, 4)
+FIELD(VP

[Qemu-devel] [PATCH V2 03/10] qemu-clk: allow to bind two clocks together

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This introduces the clock binding and the update part.
When the qemu_clk_rate_update(qemu_clk, int) function is called:
  * The clock callback is called on the qemu_clk so it can change the rate.
  * The qemu_clk_rate_update function is called on all the driven clock.

Signed-off-by: KONRAD Frederic 

V1 -> V2:
  * Rename qemu_clk_on_rate_update_cb to QEMUClkRateUpdateCallback and
move the pointer to the structure instead of having a pointer-to-function
type.
---
 include/qemu/qemu-clock.h | 67 +++
 qemu-clock.c  | 56 +++
 2 files changed, 123 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 3e692d3..6d30299 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -30,12 +30,25 @@
 #define TYPE_CLOCK "qemu-clk"
 #define QEMU_CLOCK(obj) OBJECT_CHECK(struct qemu_clk, (obj), TYPE_CLOCK)
 
+typedef struct ClkList ClkList;
+typedef uint64_t QEMUClkRateUpdateCallback(void *opaque, uint64_t rate);
+
 typedef struct qemu_clk {
 /*< private >*/
 Object parent_obj;
 char *name;/* name of this clock in the device. */
+uint64_t in_rate;  /* rate of the clock which drive this pin. */
+uint64_t out_rate; /* rate of this clock pin. */
+void *opaque;
+QEMUClkRateUpdateCallback *cb;
+QLIST_HEAD(, ClkList) bound;
 } *qemu_clk;
 
+struct ClkList {
+qemu_clk clk;
+QLIST_ENTRY(ClkList) node;
+};
+
 /**
  * qemu_clk_device_add_clock:
  * @dev: the device on which the clock needs to be added.
@@ -59,4 +72,58 @@ void qemu_clk_device_add_clock(DeviceState *dev, qemu_clk 
clk,
  */
 qemu_clk qemu_clk_device_get_clock(DeviceState *dev, const char *name);
 
+/**
+ * qemu_clk_bind_clock:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Connect the clock together. This is unidirectional so a
+ * qemu_clk_update_rate will go from @out to @in.
+ *
+ */
+void qemu_clk_bind_clock(qemu_clk out, qemu_clk in);
+
+/**
+ * qemu_clk_unbind:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Disconnect the clocks if they were bound together.
+ *
+ */
+void qemu_clk_unbind(qemu_clk out, qemu_clk in);
+
+/**
+ * qemu_clk_update_rate:
+ * @clk: the clock to update.
+ * @rate: the new rate in Hz.
+ *
+ * Update the @clk to the new @rate.
+ *
+ */
+void qemu_clk_update_rate(qemu_clk clk, uint64_t rate);
+
+/**
+ * qemu_clk_refresh:
+ * @clk: the clock to be refreshed.
+ *
+ * If a model alters the topology of a clock tree, it must call this function 
on
+ * the clock source to refresh the clock tree.
+ *
+ */
+void qemu_clk_refresh(qemu_clk clk);
+
+/**
+ * qemu_clk_set_callback:
+ * @clk: the clock associated to the callback.
+ * @cb: the function which is called when a refresh happen on the clock @clk.
+ * @opaque: the opaque data passed to the callback.
+ *
+ * Set the callback @cb which will be called when the clock @clk is updated.
+ *
+ */
+void qemu_clk_set_callback(qemu_clk clk,
+   QEMUClkRateUpdateCallback *cb,
+   void *opaque);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index 803deb3..8c12368 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -37,6 +37,62 @@
 }\
 } while (0);
 
+void qemu_clk_refresh(qemu_clk clk)
+{
+qemu_clk_update_rate(clk, clk->in_rate);
+}
+
+void qemu_clk_update_rate(qemu_clk clk, uint64_t rate)
+{
+ClkList *child;
+
+clk->in_rate = rate;
+clk->out_rate = rate;
+
+if (clk->cb) {
+clk->out_rate = clk->cb(clk->opaque, rate);
+}
+
+DPRINTF("%s output rate updated to %" PRIu64 "\n",
+object_get_canonical_path(OBJECT(clk)),
+clk->out_rate);
+
+QLIST_FOREACH(child, &clk->bound, node) {
+qemu_clk_update_rate(child->clk, clk->out_rate);
+}
+}
+
+void qemu_clk_bind_clock(qemu_clk out, qemu_clk in)
+{
+ClkList *child;
+
+child = g_malloc(sizeof(child));
+assert(child);
+child->clk = in;
+QLIST_INSERT_HEAD(&out->bound, child, node);
+qemu_clk_update_rate(in, out->out_rate);
+}
+
+void qemu_clk_unbind(qemu_clk out, qemu_clk in)
+{
+ClkList *child, *next;
+
+QLIST_FOREACH_SAFE(child, &out->bound, node, next) {
+if (child->clk == in) {
+QLIST_REMOVE(child, node);
+g_free(child);
+}
+}
+}
+
+void qemu_clk_set_callback(qemu_clk clk,
+   QEMUClkRateUpdateCallback *cb,
+   void *opaque)
+{
+clk->cb = cb;
+clk->opaque = opaque;
+}
+
 void qemu_clk_device_add_clock(DeviceState *dev, qemu_clk clk,
const char *name)
 {
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 02/10] qemu-clk: allow to add a clock to a device

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This allows to add a clock to a DeviceState.
Contrary to gpios, the clock pins are not contained in the DeviceState but
with the child property so they can appears in the qom-tree.

Signed-off-by: KONRAD Frederic 

V1 -> V2:
  * Rename the function use 'add' instead of 'attach'
---
 include/qemu/qemu-clock.h | 24 +++-
 qemu-clock.c  | 23 +++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index e7acd68..3e692d3 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -33,8 +33,30 @@
 typedef struct qemu_clk {
 /*< private >*/
 Object parent_obj;
+char *name;/* name of this clock in the device. */
 } *qemu_clk;
 
-#endif /* QEMU_CLOCK_H */
+/**
+ * qemu_clk_device_add_clock:
+ * @dev: the device on which the clock needs to be added.
+ * @clk: the clock which needs to be added.
+ * @name: the name of the clock can't be NULL.
+ *
+ * Add @clk to device @dev as a clock named @name.
+ *
+ */
+void qemu_clk_device_add_clock(DeviceState *dev, qemu_clk clk,
+   const char *name);
 
+/**
+ * qemu_clk_device_get_clock:
+ * @dev: the device which contains the clock.
+ * @name: the name of the clock.
+ *
+ * Get the clock named @name contained in the device @dev, or NULL if not 
found.
+ *
+ * Returns the clock named @name contained in @dev.
+ */
+qemu_clk qemu_clk_device_get_clock(DeviceState *dev, const char *name);
 
+#endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index ceea98d..803deb3 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -25,6 +25,7 @@
 #include "qemu/qemu-clock.h"
 #include "hw/hw.h"
 #include "qemu/log.h"
+#include "qapi/error.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -36,6 +37,28 @@
 }\
 } while (0);
 
+void qemu_clk_device_add_clock(DeviceState *dev, qemu_clk clk,
+   const char *name)
+{
+assert(name);
+assert(!clk->name);
+object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort);
+clk->name = g_strdup(name);
+}
+
+qemu_clk qemu_clk_device_get_clock(DeviceState *dev, const char *name)
+{
+gchar *path = NULL;
+Object *clk;
+bool ambiguous;
+
+path = g_strdup_printf("%s/%s", object_get_canonical_path(OBJECT(dev)),
+   name);
+clk = object_resolve_path(path, &ambiguous);
+g_free(path);
+return QEMU_CLOCK(clk);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
1.8.3.1




[Qemu-devel] [PATCH V2 00/10] Clock framework API.

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

Hi,

This is the second version of the clock framework API it contains:

  * The first 6 patches which introduce the framework.
  * The 7th patch which introduces a fixed-clock model.
  * The rest which gives an example how to model a PLL from the existing
zynqmp-crf extracted from the qemu xilinx tree.

No specific behavior is expected yet when the CRF register set is accessed but
the user can see for example the dp_video_ref and vpll_to_lpd rate changing in
the monitor with the "info qtree" command when the vpll_ctrl register is
modified.

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
qemu-clk "dbg_trace" 0
qemu-clk "dp_stc_ref" 0
qemu-clk "dpll_to_lpd" 1250
qemu-clk "acpu_clk" 0
qemu-clk "pcie_ref" 0
qemu-clk "topsw_main" 0
qemu-clk "topsw_lsbus" 0
qemu-clk "dp_audio_ref" 0
qemu-clk "sata_ref" 0
qemu-clk "dp_video_ref" 1428571
qemu-clk "vpll_clk" 5000
qemu-clk "apll_to_lpd" 1250
qemu-clk "dpll_clk" 5000
qemu-clk "gpu_ref" 0
qemu-clk "aux_refclk" 0
qemu-clk "video_clk" 2700
qemu-clk "gdma_ref" 0
qemu-clk "gt_crx_ref_clk" 0
qemu-clk "dbg_fdp" 0
qemu-clk "apll_clk" 5000
qemu-clk "pss_alt_ref_clk" 0
qemu-clk "ddr" 0
qemu-clk "dbg_tstmp" 0
qemu-clk "pss_ref_clk" 5000
qemu-clk "dpdma_ref" 0
qemu-clk "vpll_to_lpd" 1250
mmio fd1a/010c

This series is based on the current master
(a9e404600a9bd1e6a26431fc89e5069092e67f14).

Thanks,
Fred

V1 -> V2:
  * Rebased on current master.
  * Some function renamed and documentation fixed.

RFC -> V1:
  * Rebased on current master.
  * The docs has been fixed.
  * qemu_clk_init_device helper has been provided to ease the initialization
of the devices.

KONRAD Frederic (10):
  qemu-clk: introduce qemu-clk qom object
  qemu-clk: allow to add a clock to a device
  qemu-clk: allow to bind two clocks together
  qemu-clk: introduce an init array to help the device construction
  qdev-monitor: print the device's clock with info qtree
  docs: add qemu-clock documentation
  introduce fixed-clock
  introduce zynqmp_crf
  zynqmp: add the zynqmp_crf to the platform
  zynqmp: add reference clock

 Makefile.objs |   1 +
 docs/clock.txt| 108 +
 hw/arm/xlnx-zynqmp.c  |  56 +++
 hw/misc/Makefile.objs |   2 +
 hw/misc/fixed-clock.c |  88 
 hw/misc/xilinx_zynqmp_crf.c   | 968 ++
 include/hw/arm/xlnx-zynqmp.h  |   8 +
 include/hw/misc/fixed-clock.h |  30 ++
 include/qemu/qemu-clock.h | 161 +++
 qdev-monitor.c|   2 +
 qemu-clock.c  | 174 
 11 files changed, 1598 insertions(+)
 create mode 100644 docs/clock.txt
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c
 create mode 100644 include/hw/misc/fixed-clock.h
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

-- 
1.8.3.1




[Qemu-devel] [PATCH V2 04/10] qemu-clk: introduce an init array to help the device construction

2017-01-26 Thread fred . konrad
From: KONRAD Frederic 

This introduces a clock init array to ease the clock tree construction.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h | 23 +++
 qemu-clock.c  | 17 +
 2 files changed, 40 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 6d30299..45f8766 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -49,6 +49,29 @@ struct ClkList {
 QLIST_ENTRY(ClkList) node;
 };
 
+typedef struct ClockInitElement {
+const char *name;  /* Name to give to the clock. */
+size_t offset; /* Offset of the qemu_clk field in the object. */
+QEMUClkRateUpdateCallback *cb;
+} ClockInitElement;
+
+#define DEVICE_CLOCK(_state, _field, _cb) {  \
+.name = #_field, \
+.offset = offsetof(_state, _field),  \
+.cb = _cb\
+}
+
+#define DEVICE_CLOCK_END() { \
+.name = NULL \
+}
+
+/**
+ * qemu_clk_init_device:
+ * @obj: the Object which need to be initialized.
+ * @array: the array of ClockInitElement to be used.
+ */
+void qemu_clk_init_device(Object *obj, ClockInitElement *array);
+
 /**
  * qemu_clk_device_add_clock:
  * @dev: the device on which the clock needs to be added.
diff --git a/qemu-clock.c b/qemu-clock.c
index 8c12368..300e38f 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -26,6 +26,7 @@
 #include "hw/hw.h"
 #include "qemu/log.h"
 #include "qapi/error.h"
+#include "hw/qdev-core.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -37,6 +38,22 @@
 }\
 } while (0);
 
+void qemu_clk_init_device(Object *obj, ClockInitElement *array)
+{
+qemu_clk *cur = NULL;
+
+while (array->name != NULL) {
+DPRINTF("init clock named %s\n", array->name);
+cur = (((void *)obj) + array->offset);
+*cur = QEMU_CLOCK(object_new(TYPE_CLOCK));
+qemu_clk_device_add_clock(DEVICE(obj), *cur, array->name);
+if (array->cb) {
+qemu_clk_set_callback(*cur, array->cb, obj);
+}
+array++;
+}
+}
+
 void qemu_clk_refresh(qemu_clk clk)
 {
 qemu_clk_update_rate(clk, clk->in_rate);
-- 
1.8.3.1




[Qemu-devel] [PATCH V1 10/10] zynqmp: add reference clock

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This adds some fixed reference clock to the zynqmp platform.
They will feed the zynqmp_crf block.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 42 ++
 include/hw/arm/xlnx-zynqmp.h |  6 ++
 2 files changed, 48 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 05cf99b..1096dc4 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -24,6 +24,7 @@
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
+#include "qemu/qemu-clock.h"
 
 #define GIC_NUM_SPI_INTR 160
 
@@ -182,6 +183,22 @@ static void xlnx_zynqmp_init(Object *obj)
 qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
 object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
   &error_abort);
+
+s->pss_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_ref_clk", s->pss_ref_clk,
+  &error_abort);
+object_property_set_int(s->pss_ref_clk, 5000, "rate", &error_abort);
+s->video_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "video_clk", s->video_clk, &error_abort);
+object_property_set_int(s->video_clk, 2700, "rate", &error_abort);
+s->pss_alt_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_alt_ref_clk", s->pss_alt_ref_clk,
+  &error_abort);
+s->aux_refclk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "aux_refclk", s->aux_refclk, &error_abort);
+s->gt_crx_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "gt_crx_ref_clk", s->gt_crx_ref_clk,
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -429,6 +446,31 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
+
+/* Bound the clock */
+qemu_clk_bind_clock(qemu_clk_get_pin(DEVICE(s->pss_ref_clk), "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "pss_ref_clk"));
+
+qemu_clk_bind_clock(qemu_clk_get_pin(DEVICE(s->video_clk), "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "video_clk"));
+
+qemu_clk_bind_clock(qemu_clk_get_pin(DEVICE(s->pss_alt_ref_clk),
+  "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "pss_alt_ref_clk"));
+
+qemu_clk_bind_clock(qemu_clk_get_pin(DEVICE(s->aux_refclk), "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "aux_refclk"));
+
+qemu_clk_bind_clock(qemu_clk_get_pin(DEVICE(s->gt_crx_ref_clk),
+  "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "gt_crx_ref_clk"));
+
+object_property_set_bool(s->crf, true, "realized", &err);
+object_property_set_bool(s->pss_ref_clk, true, "realized", &err);
+object_property_set_bool(s->video_clk, true, "realized", &err);
+object_property_set_bool(s->pss_alt_ref_clk, true, "realized", &err);
+object_property_set_bool(s->aux_refclk, true, "realized", &err);
+object_property_set_bool(s->gt_crx_ref_clk, true, "realized", &err);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 379a17a..d0cc57f 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -28,6 +28,7 @@
 #include "hw/ssi/xilinx_spips.h"
 #include "hw/dma/xlnx_dpdma.h"
 #include "hw/display/xlnx_dp.h"
+#include "hw/misc/fixed-clock.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
@@ -86,6 +87,11 @@ typedef struct XlnxZynqMPState {
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
+Object *pss_ref_clk;
+Object *video_clk;
+Object *pss_alt_ref_clk;
+Object *aux_refclk;
+Object *gt_crx_ref_clk;
 Object *crf;
 
 char *boot_cpu;
-- 
2.5.5




[Qemu-devel] [PATCH V1 08/10] introduce zynqmp_crf

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This introduce Xilinx zynqmp-crf.
It is extracted from the qemu xilinx tree 
(02d2f0203dd489ed30d9c8d90c14a52c57332b25) and is used as
an example for the clock framework.
---
 hw/misc/Makefile.objs   |   1 +
 hw/misc/xilinx_zynqmp_crf.c | 968 
 2 files changed, 969 insertions(+)
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 2670c2d..60f9f4d 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -43,6 +43,7 @@ obj-$(CONFIG_RASPI) += bcm2835_property.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
+obj-$(CONFIG_ZYNQ) += xilinx_zynqmp_crf.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
diff --git a/hw/misc/xilinx_zynqmp_crf.c b/hw/misc/xilinx_zynqmp_crf.c
new file mode 100644
index 000..e4b9225
--- /dev/null
+++ b/hw/misc/xilinx_zynqmp_crf.c
@@ -0,0 +1,968 @@
+/*
+ * QEMU model of the CRF_APB APB control registers for clock controller. The
+ * RST_ctrl_fpd will be added to this as well
+ *
+ * Copyright (c) 2014 Xilinx Inc.
+ *
+ * Autogenerated by xregqemu.py 2014-01-22.
+ *
+ * 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/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/qemu-clock.h"
+
+#ifndef XILINX_CRF_APB_ERR_DEBUG
+#define XILINX_CRF_APB_ERR_DEBUG 0
+#endif
+
+#define TYPE_XILINX_CRF_APB "xlnx.zynqmp_crf"
+
+#define XILINX_CRF_APB(obj) \
+ OBJECT_CHECK(CRF_APB, (obj), TYPE_XILINX_CRF_APB)
+
+REG32(ERR_CTRL, 0x0)
+FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x4)
+FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_MASK, 0x8)
+FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_ENABLE, 0xc)
+FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_DISABLE, 0x10)
+FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(CRF_ECO, 0x18)
+REG32(APLL_CTRL, 0x20)
+FIELD(APLL_CTRL, POST_SRC, 24, 3)
+FIELD(APLL_CTRL, PRE_SRC, 20, 3)
+FIELD(APLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(APLL_CTRL, DIV2, 16, 1)
+FIELD(APLL_CTRL, FBDIV, 8, 7)
+FIELD(APLL_CTRL, BYPASS, 3, 1)
+FIELD(APLL_CTRL, RESET, 0, 1)
+REG32(APLL_CFG, 0x24)
+FIELD(APLL_CFG, LOCK_DLY, 25, 7)
+FIELD(APLL_CFG, LOCK_CNT, 13, 10)
+FIELD(APLL_CFG, LFHF, 10, 2)
+FIELD(APLL_CFG, CP, 5, 4)
+FIELD(APLL_CFG, RES, 0, 4)
+REG32(APLL_FRAC_CFG, 0x28)
+FIELD(APLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(APLL_FRAC_CFG, SEED, 22, 3)
+FIELD(APLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(APLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(APLL_FRAC_CFG, DATA, 0, 16)
+REG32(DPLL_CTRL, 0x2c)
+FIELD(DPLL_CTRL, POST_SRC, 24, 3)
+FIELD(DPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(DPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(DPLL_CTRL, DIV2, 16, 1)
+FIELD(DPLL_CTRL, FBDIV, 8, 7)
+FIELD(DPLL_CTRL, BYPASS, 3, 1)
+FIELD(DPLL_CTRL, RESET, 0, 1)
+REG32(DPLL_CFG, 0x30)
+FIELD(DPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(DPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(DPLL_CFG, LFHF, 10, 2)
+FIELD(DPLL_CFG, CP, 5, 4)
+FIELD(DPLL_CFG, RES, 0, 4)
+REG32(DPLL_FRAC_CFG, 0x34)
+FIELD(DPLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(DPLL_FRAC_CFG, SEED, 22, 3)
+FIELD(DPLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(DPLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(DPLL_FRAC_CFG, DATA, 0, 16)
+REG32(VPLL_CTRL, 0x38)
+FIELD(VPLL_CTRL, POST_SRC, 24, 3)
+FIELD(VPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(VPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(VPLL_CTRL, DIV2, 16, 1)
+FIELD(VPLL_CTRL, FBDIV, 8, 7)
+FIELD(VPLL_CTRL, BYPASS, 3, 1)
+FIELD(VPLL_CTRL, RESET, 0, 1)
+REG32(VPLL_CFG, 0x3c)
+FIELD(VPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(VPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(VPLL_CFG, LFHF, 10, 2)
+FIELD(VPLL_CFG, CP, 5, 4)
+FIELD(VP

[Qemu-devel] [PATCH V1 07/10] introduce fixed-clock

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This is a fixed clock device.
It justs behave as an empty device with a parametrable output rate.

Signed-off-by: KONRAD Frederic 
---
 hw/misc/Makefile.objs |  1 +
 hw/misc/fixed-clock.c | 88 +++
 include/hw/misc/fixed-clock.h | 30 +++
 3 files changed, 119 insertions(+)
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 include/hw/misc/fixed-clock.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 1a89615..2670c2d 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -53,3 +53,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-y += fixed-clock.o
diff --git a/hw/misc/fixed-clock.c b/hw/misc/fixed-clock.c
new file mode 100644
index 000..7d0a93b
--- /dev/null
+++ b/hw/misc/fixed-clock.c
@@ -0,0 +1,88 @@
+/*
+ * Fixed clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev.h"
+#include "hw/misc/fixed-clock.h"
+#include "qemu/qemu-clock.h"
+#include "qapi/error.h"
+
+#ifndef DEBUG_FIXED_CLOCK
+#define DEBUG_FIXED_CLOCK 0
+#endif
+
+#define DPRINTF(fmt, ...) do {   \
+if (DEBUG_FIXED_CLOCK) { \
+qemu_log(__FILE__": " fmt , ## __VA_ARGS__); \
+}\
+} while (0);
+
+typedef struct {
+DeviceState parent_obj;
+
+uint32_t rate;
+struct qemu_clk out;
+} FixedClock;
+
+static Property fixed_clock_properties[] = {
+DEFINE_PROP_UINT32("rate", FixedClock, rate, 0),
+DEFINE_PROP_END_OF_LIST()
+};
+
+static void fixed_clock_realizefn(DeviceState *dev, Error **errp)
+{
+FixedClock *s = FIXED_CLOCK(dev);
+
+qemu_clk_update_rate(&s->out, s->rate);
+}
+
+static void fixed_clock_instance_init(Object *obj)
+{
+FixedClock *s = FIXED_CLOCK(obj);
+
+object_initialize(&s->out, sizeof(s->out), TYPE_CLOCK);
+qemu_clk_attach_to_device(DEVICE(obj), &s->out, "clk_out");
+}
+
+static void fixed_clock_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = fixed_clock_realizefn;
+dc->props = fixed_clock_properties;
+}
+
+static const TypeInfo fixed_clock_info = {
+.name  = TYPE_FIXED_CLOCK,
+.parent= TYPE_DEVICE,
+.instance_size = sizeof(FixedClock),
+.instance_init = fixed_clock_instance_init,
+.class_init= fixed_clock_class_init,
+};
+
+static void fixed_clock_register_types(void)
+{
+type_register_static(&fixed_clock_info);
+}
+
+type_init(fixed_clock_register_types);
diff --git a/include/hw/misc/fixed-clock.h b/include/hw/misc/fixed-clock.h
new file mode 100644
index 000..1376444
--- /dev/null
+++ b/include/hw/misc/fixed-clock.h
@@ -0,0 +1,30 @@
+/*
+ * Fixed clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad   
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef FIXED_CLOCK_H
+#define FIXED_CLOCK_H
+
+#define TYPE_FIXED_CLOCK "fixed-clock"
+#define FIXED_CLOCK(obj) OBJECT_CHECK(FixedClock, (obj), TYPE_FIXED_CLOCK)
+
+#endif /* FIXED_CLOCK_H */
-- 
2.5.5




[Qemu-devel] [PATCH V1 09/10] zynqmp: add the zynqmp_crf to the platform

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This adds the zynqmp_crf to the zynqmp platform.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 7 +++
 include/hw/arm/xlnx-zynqmp.h | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 0d86ba3..05cf99b 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -177,6 +177,11 @@ static void xlnx_zynqmp_init(Object *obj)
 
 object_initialize(&s->dpdma, sizeof(s->dpdma), TYPE_XLNX_DPDMA);
 qdev_set_parent_bus(DEVICE(&s->dpdma), sysbus_get_default());
+
+s->crf = object_new("xlnx.zynqmp_crf");
+qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
+object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -422,6 +427,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
  &error_abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->dpdma), 0, DPDMA_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
+
+sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index c2931bf..379a17a 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -86,6 +86,8 @@ typedef struct XlnxZynqMPState {
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
+Object *crf;
+
 char *boot_cpu;
 ARMCPU *boot_cpu_ptr;
 
-- 
2.5.5




[Qemu-devel] [PATCH V1 03/10] qemu-clk: allow to bind two clocks together

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This introduces the clock binding and the update part.
When the qemu_clk_rate_update(qemu_clk, int) function is called:
  * The clock callback is called on the qemu_clk so it can change the rate.
  * The qemu_clk_rate_update function is called on all the driven clock.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h | 66 +++
 qemu-clock.c  | 56 
 2 files changed, 122 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 1d56a2e..d575566 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -27,15 +27,29 @@
 #include "qemu/osdep.h"
 #include "qom/object.h"
 
+typedef uint64_t (*qemu_clk_on_rate_update_cb)(void *opaque, uint64_t rate);
+
 #define TYPE_CLOCK "qemu-clk"
 #define QEMU_CLOCK(obj) OBJECT_CHECK(struct qemu_clk, (obj), TYPE_CLOCK)
 
+typedef struct ClkList ClkList;
+
 typedef struct qemu_clk {
 /*< private >*/
 Object parent_obj;
 char *name;/* name of this clock in the device. */
+uint64_t in_rate;  /* rate of the clock which drive this pin. */
+uint64_t out_rate; /* rate of this clock pin. */
+void *opaque;
+qemu_clk_on_rate_update_cb cb;
+QLIST_HEAD(, ClkList) bound;
 } *qemu_clk;
 
+struct ClkList {
+qemu_clk clk;
+QLIST_ENTRY(ClkList) node;
+};
+
 /**
  * qemu_clk_attach_to_device:
  * @dev: the device on which the clock need to be attached.
@@ -59,4 +73,56 @@ void qemu_clk_attach_to_device(DeviceState *dev, qemu_clk 
clk,
  */
 qemu_clk qemu_clk_get_pin(DeviceState *dev, const char *name);
 
+/**
+ * qemu_clk_bind_clock:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Connect the clock together. This is unidirectional so a
+ * qemu_clk_update_rate will go from @out to @in.
+ *
+ */
+void qemu_clk_bind_clock(qemu_clk out, qemu_clk in);
+
+/**
+ * qemu_clk_unbound:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Disconnect the clocks if they were bound together.
+ *
+ */
+void qemu_clk_unbind(qemu_clk out, qemu_clk in);
+
+/**
+ * qemu_clk_update_rate:
+ * @clk: the clock to update.
+ * @rate: the new rate.
+ *
+ * Update the @clk to the new @rate.
+ *
+ */
+void qemu_clk_update_rate(qemu_clk clk, uint64_t rate);
+
+/**
+ * qemu_clk_refresh:
+ * @clk: the clock to be refreshed.
+ *
+ * If a model alters the topology of a clock tree, it must call this function
+ * to refresh the clock tree.
+ *
+ */
+void qemu_clk_refresh(qemu_clk clk);
+
+/**
+ * qemu_clk_set_callback:
+ * @clk: the clock where to set the callback.
+ * @cb: the callback to associate to the callback.
+ * @opaque: the opaque data passed to the calback.
+ *
+ */
+void qemu_clk_set_callback(qemu_clk clk,
+   qemu_clk_on_rate_update_cb cb,
+   void *opaque);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index 0ba6caf..541f615 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -37,6 +37,62 @@
 }\
 } while (0);
 
+void qemu_clk_refresh(qemu_clk clk)
+{
+qemu_clk_update_rate(clk, clk->in_rate);
+}
+
+void qemu_clk_update_rate(qemu_clk clk, uint64_t rate)
+{
+ClkList *child;
+
+clk->in_rate = rate;
+clk->out_rate = rate;
+
+if (clk->cb) {
+clk->out_rate = clk->cb(clk->opaque, rate);
+}
+
+DPRINTF("%s output rate updated to %" PRIu64 "\n",
+object_get_canonical_path(OBJECT(clk)),
+clk->out_rate);
+
+QLIST_FOREACH(child, &clk->bound, node) {
+qemu_clk_update_rate(child->clk, clk->out_rate);
+}
+}
+
+void qemu_clk_bind_clock(qemu_clk out, qemu_clk in)
+{
+ClkList *child;
+
+child = g_malloc(sizeof(child));
+assert(child);
+child->clk = in;
+QLIST_INSERT_HEAD(&out->bound, child, node);
+qemu_clk_update_rate(in, out->out_rate);
+}
+
+void qemu_clk_unbind(qemu_clk out, qemu_clk in)
+{
+ClkList *child, *next;
+
+QLIST_FOREACH_SAFE(child, &out->bound, node, next) {
+if (child->clk == in) {
+QLIST_REMOVE(child, node);
+g_free(child);
+}
+}
+}
+
+void qemu_clk_set_callback(qemu_clk clk,
+   qemu_clk_on_rate_update_cb cb,
+   void *opaque)
+{
+clk->cb = cb;
+clk->opaque = opaque;
+}
+
 void qemu_clk_attach_to_device(DeviceState *dev, qemu_clk clk,
const char *name)
 {
-- 
2.5.5




[Qemu-devel] [PATCH V1 06/10] docs: add qemu-clock documentation

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This adds the qemu-clock documentation.

Signed-off-by: KONRAD Frederic 
---
 docs/clock.txt | 109 +
 1 file changed, 109 insertions(+)
 create mode 100644 docs/clock.txt

diff --git a/docs/clock.txt b/docs/clock.txt
new file mode 100644
index 000..b25c5ab
--- /dev/null
+++ b/docs/clock.txt
@@ -0,0 +1,109 @@
+
+What is a QEMU_CLOCK
+
+
+A QEMU_CLOCK is a QOM Object developed for the purpose of modeling a clock tree
+with QEMU.
+
+It only simulates the clock by keeping a copy of the current frequency and
+doesn't model the signal itself such as pin toggle or duty cycle.
+
+It allows to model the impact of badly configured PLL, clock source selection
+or disabled clock on the models.
+
+Binding the clock together to create a tree
+===
+
+In order to create a clock tree with QEMU_CLOCK two or more clock must be bound
+together. Let's say there are two clocks clk_a and clk_b:
+Using qemu_clk_bind(clk_a, clk_b) will bind clk_a and clk_b.
+
+Binding two qemu-clk together creates a unidirectional link which means that
+changing the rate of clk_a will propagate to clk_b and not the opposite.
+The binding process automatically refreshes clk_b rate.
+
+Clock can be bound and unbound during execution for modeling eg: a clock
+selector.
+
+A clock can drive more than one other clock. eg with this code:
+qemu_clk_bind(clk_a, clk_b);
+qemu_clk_bind(clk_a, clk_c);
+
+A clock rate change one clk_a will propagate to clk_b and clk_c.
+
+Implementing a callback on a rate change
+
+
+The function prototype is the following:
+typedef uint64_t (*qemu_clk_rate_change_cb)(void *opaque, uint64_t rate);
+
+It's main goal is to modify the rate before it's passed to the next clocks in
+the tree.
+
+eg: for a 4x PLL the function will be:
+uint64_t qemu_clk_rate_change_cb(void *opaque, uint64_t rate)
+{
+return 4 * rate;
+}
+
+To set the callback for the clock:
+void qemu_clk_set_callback(qemu_clk clk, qemu_clk_on_rate_update_cb cb,
+   void *opaque);
+can be called.
+
+The rate update process
+===
+
+The rate update happen in this way:
+When a model wants to update a clock frequency (eg: based on a register change
+or something similar) it will call qemu_clk_update_rate(..) on the clock:
+  * The callback associated to the clock is called with the new rate.
+  * qemu_clk_update_rate(..) is then called on all bound clock with the
+value returned by the callback.
+
+NOTE: When no callback is attached, the clock qemu_clk_update_rate(..) is 
called
+with the unmodified rate.
+
+Attaching a QEMU_CLOCK to a DeviceState
+===
+
+Attaching a qemu-clk to a DeviceState is required to be able to get the clock
+outside the model through qemu_clk_get_pin(..).
+
+It is also required to be able to print the clock and its rate with info qtree.
+For example:
+
+  type System
+  dev: xlnx.zynqmp_crf, id ""
+gpio-out "sysbus-irq" 1
+gpio-out "RST_A9" 4
+qemu-clk "dbg_trace" 0
+qemu-clk "vpll_to_lpd" 62500
+qemu-clk "dp_stc_ref" 0
+qemu-clk "dpll_to_lpd" 1250
+qemu-clk "acpu_clk" 0
+qemu-clk "pcie_ref" 0
+qemu-clk "topsw_main" 0
+qemu-clk "topsw_lsbus" 0
+qemu-clk "dp_audio_ref" 0
+qemu-clk "sata_ref" 0
+qemu-clk "dp_video_ref" 71428568
+qemu-clk "vpll_clk" 25
+qemu-clk "apll_to_lpd" 1250
+qemu-clk "dpll_clk" 5000
+qemu-clk "gpu_ref" 0
+qemu-clk "aux_refclk" 0
+qemu-clk "video_clk" 2700
+qemu-clk "gdma_ref" 0
+qemu-clk "gt_crx_ref_clk" 0
+qemu-clk "dbg_fdp" 0
+qemu-clk "apll_clk" 5000
+qemu-clk "pss_alt_ref_clk" 0
+qemu-clk "ddr" 0
+qemu-clk "pss_ref_clk" 5000
+qemu-clk "dpdma_ref" 0
+qemu-clk "dbg_tstmp" 0
+mmio fd1a/010c
+
+This way a DeviceState can have multiple clock input or output.
+
-- 
2.5.5




[Qemu-devel] [PATCH V1 05/10] qdev-monitor: print the device's clock with info qtree

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This prints the clock attached to a DeviceState when using "info qtree" monitor
command.

For example:

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
gpio-out "RST_A9" 4
qemu-clk "dbg_trace" 0.0
qemu-clk "vpll_to_lpd" 1250.0
qemu-clk "dp_stc_ref" 0.0
qemu-clk "dpll_to_lpd" 1250.0
qemu-clk "acpu_clk" 0.0
qemu-clk "pcie_ref" 0.0
qemu-clk "topsw_main" 0.0
qemu-clk "topsw_lsbus" 0.0
qemu-clk "dp_audio_ref" 0.0
qemu-clk "sata_ref" 0.0
qemu-clk "dp_video_ref" 1428571.4
qemu-clk "vpll_clk" 5000.0
qemu-clk "apll_to_lpd" 1250.0
qemu-clk "dpll_clk" 5000.0
qemu-clk "gpu_ref" 0.0
qemu-clk "aux_refclk" 0.0
qemu-clk "video_clk" 2700.0
qemu-clk "gdma_ref" 0.0
qemu-clk "gt_crx_ref_clk" 0.0
qemu-clk "dbg_fdp" 0.0
qemu-clk "apll_clk" 5000.0
qemu-clk "pss_alt_ref_clk" 0.0
qemu-clk "ddr" 0.0
qemu-clk "pss_ref_clk" 5000.0
qemu-clk "dpdma_ref" 0.0
qemu-clk "dbg_tstmp" 0.0
mmio fd1a/010c

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h |  9 +
 qdev-monitor.c|  2 ++
 qemu-clock.c  | 28 
 3 files changed, 39 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 72062de..a517afd 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -148,4 +148,13 @@ void qemu_clk_set_callback(qemu_clk clk,
qemu_clk_on_rate_update_cb cb,
void *opaque);
 
+/**
+ * qemu_clk_print:
+ * @dev: the device for which the clock need to be printed.
+ *
+ * Print the clock information for a given device.
+ *
+ */
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 4f78ecb..4e741f2 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "qemu/help_option.h"
 #include "sysemu/block-backend.h"
+#include "qemu/qemu-clock.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -685,6 +686,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int 
indent)
 ngl->num_out);
 }
 }
+qemu_clk_print(mon, dev, indent);
 class = object_get_class(OBJECT(dev));
 do {
 qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
diff --git a/qemu-clock.c b/qemu-clock.c
index 5c799bc..a380341 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -27,6 +27,7 @@
 #include "qemu/log.h"
 #include "qapi/error.h"
 #include "hw/qdev-core.h"
+#include "monitor/monitor.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -132,6 +133,33 @@ qemu_clk qemu_clk_get_pin(DeviceState *dev, const char 
*name)
 return QEMU_CLOCK(clk);
 }
 
+struct print_opaque {
+Monitor *mon;
+int indent;
+};
+
+static int qemu_clk_print_rec(Object *obj, void *opaque)
+{
+qemu_clk clk = (qemu_clk)(object_dynamic_cast(obj, TYPE_CLOCK));
+struct print_opaque *po = opaque;
+
+if (clk) {
+monitor_printf(po->mon, "%*s" "qemu-clk \"%s\" %" PRIu64 "\n",
+   po->indent, " ", clk->name, clk->out_rate);
+}
+
+return 0;
+}
+
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent)
+{
+struct print_opaque po;
+
+po.indent = indent;
+po.mon = mon;
+object_child_foreach(OBJECT(dev), qemu_clk_print_rec, &po);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
2.5.5




[Qemu-devel] [PATCH V1 04/10] qemu-clk: introduce an init array to help the device construction

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This introduces a clock init array to ease the clock tree construction.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h | 23 +++
 qemu-clock.c  | 17 +
 2 files changed, 40 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index d575566..72062de 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -50,6 +50,29 @@ struct ClkList {
 QLIST_ENTRY(ClkList) node;
 };
 
+typedef struct ClockInitElement {
+const char *name;  /* Name to give to the clock. */
+size_t offset; /* Offset of the qemu_clk field in the object. */
+qemu_clk_on_rate_update_cb cb;
+} ClockInitElement;
+
+#define DEVICE_CLOCK(_state, _field, _cb) {  \
+.name = #_field, \
+.offset = offsetof(_state, _field),  \
+.cb = _cb\
+}
+
+#define DEVICE_CLOCK_END() { \
+.name = NULL \
+}
+
+/**
+ * qemu_clk_init_device:
+ * @obj: the Object which need to be initialized.
+ * @array: the array of ClockInitElement to be used.
+ */
+void qemu_clk_init_device(Object *obj, ClockInitElement *array);
+
 /**
  * qemu_clk_attach_to_device:
  * @dev: the device on which the clock need to be attached.
diff --git a/qemu-clock.c b/qemu-clock.c
index 541f615..5c799bc 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -26,6 +26,7 @@
 #include "hw/hw.h"
 #include "qemu/log.h"
 #include "qapi/error.h"
+#include "hw/qdev-core.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -37,6 +38,22 @@
 }\
 } while (0);
 
+void qemu_clk_init_device(Object *obj, ClockInitElement *array)
+{
+qemu_clk *cur = NULL;
+
+while (array->name != NULL) {
+DPRINTF("init clock named %s\n", array->name);
+cur = (((void *)obj) + array->offset);
+*cur = QEMU_CLOCK(object_new(TYPE_CLOCK));
+qemu_clk_attach_to_device(DEVICE(obj), *cur, array->name);
+if (array->cb) {
+qemu_clk_set_callback(*cur, array->cb, obj);
+}
+array++;
+}
+}
+
 void qemu_clk_refresh(qemu_clk clk)
 {
 qemu_clk_update_rate(clk, clk->in_rate);
-- 
2.5.5




[Qemu-devel] [PATCH V1 00/10] Clock framework API.

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

Hi,

This is the first version of the clock framework API it contains:

  * The first 6 patches which introduce the framework.
  * The 7th patch which introduces a fixed-clock model.
  * The rest which gives an example how to model a PLL from the existing
zynqmp-crf extracted from the qemu xilinx tree.

No specific behavior is expected yet when the CRF register set is accessed but
the user can see for example the dp_video_ref and vpll_to_lpd rate changing in
the monitor with the "info qtree" command when the vpll_ctrl register is
modified.

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
qemu-clk "dbg_trace" 0
qemu-clk "dp_stc_ref" 0
qemu-clk "dpll_to_lpd" 1250
qemu-clk "acpu_clk" 0
qemu-clk "pcie_ref" 0
qemu-clk "topsw_main" 0
qemu-clk "topsw_lsbus" 0
qemu-clk "dp_audio_ref" 0
qemu-clk "sata_ref" 0
qemu-clk "dp_video_ref" 1428571
qemu-clk "vpll_clk" 5000
qemu-clk "apll_to_lpd" 1250
qemu-clk "dpll_clk" 5000
qemu-clk "gpu_ref" 0
qemu-clk "aux_refclk" 0
qemu-clk "video_clk" 2700
qemu-clk "gdma_ref" 0
qemu-clk "gt_crx_ref_clk" 0
qemu-clk "dbg_fdp" 0
qemu-clk "apll_clk" 5000
qemu-clk "pss_alt_ref_clk" 0
qemu-clk "ddr" 0
qemu-clk "dbg_tstmp" 0
qemu-clk "pss_ref_clk" 5000
qemu-clk "dpdma_ref" 0
qemu-clk "vpll_to_lpd" 1250
mmio fd1a/010c

This series is based on the current master
(bbc4c3f4f3c624e2de64fdcb79f4dd8c1a508e9d).

Thanks,
Fred

RFC -> V1:
  * Rebased on current master.
  * The docs has been fixed.
  * qemu_clk_init_device helper has been provided to ease the initialization
of the devices.

KONRAD Frederic (10):
  qemu-clk: introduce qemu-clk qom object
  qemu-clk: allow to attach a clock to a device
  qemu-clk: allow to bind two clocks together
  qemu-clk: introduce an init array to help the device construction
  qdev-monitor: print the device's clock with info qtree
  docs: add qemu-clock documentation
  introduce fixed-clock
  introduce zynqmp_crf
  zynqmp: add the zynqmp_crf to the platform
  zynqmp: add reference clock

 Makefile.objs |   1 +
 docs/clock.txt| 109 +
 hw/arm/xlnx-zynqmp.c  |  49 +++
 hw/misc/Makefile.objs |   2 +
 hw/misc/fixed-clock.c |  88 
 hw/misc/xilinx_zynqmp_crf.c   | 968 ++
 include/hw/arm/xlnx-zynqmp.h  |   8 +
 include/hw/misc/fixed-clock.h |  30 ++
 include/qemu/qemu-clock.h | 160 +++
 qdev-monitor.c|   2 +
 qemu-clock.c  | 174 
 11 files changed, 1591 insertions(+)
 create mode 100644 docs/clock.txt
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c
 create mode 100644 include/hw/misc/fixed-clock.h
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

-- 
2.5.5




[Qemu-devel] [PATCH V1 01/10] qemu-clk: introduce qemu-clk qom object

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This introduces qemu-clk qom object.

Signed-off-by: KONRAD Frederic 
---
 Makefile.objs |  1 +
 include/qemu/qemu-clock.h | 40 +
 qemu-clock.c  | 50 +++
 3 files changed, 91 insertions(+)
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

diff --git a/Makefile.objs b/Makefile.objs
index 02fb8e7..1809497 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -78,6 +78,7 @@ common-obj-y += backends/
 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
 
 common-obj-$(CONFIG_FDT) += device_tree.o
+common-obj-y += qemu-clock.o
 
 ##
 # qapi
diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
new file mode 100644
index 000..e7acd68
--- /dev/null
+++ b/include/qemu/qemu-clock.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef QEMU_CLOCK_H
+#define QEMU_CLOCK_H
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+
+#define TYPE_CLOCK "qemu-clk"
+#define QEMU_CLOCK(obj) OBJECT_CHECK(struct qemu_clk, (obj), TYPE_CLOCK)
+
+typedef struct qemu_clk {
+/*< private >*/
+Object parent_obj;
+} *qemu_clk;
+
+#endif /* QEMU_CLOCK_H */
+
+
diff --git a/qemu-clock.c b/qemu-clock.c
new file mode 100644
index 000..ceea98d
--- /dev/null
+++ b/qemu-clock.c
@@ -0,0 +1,50 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/qemu-clock.h"
+#include "hw/hw.h"
+#include "qemu/log.h"
+
+#ifndef DEBUG_QEMU_CLOCK
+#define DEBUG_QEMU_CLOCK 0
+#endif
+
+#define DPRINTF(fmt, args...) do {   \
+if (DEBUG_QEMU_CLOCK) {  \
+qemu_log("%s: " fmt, __func__, ## args); \
+}\
+} while (0);
+
+static const TypeInfo qemu_clk_info = {
+.name  = TYPE_CLOCK,
+.parent= TYPE_OBJECT,
+.instance_size = sizeof(struct qemu_clk),
+};
+
+static void qemu_clk_register_types(void)
+{
+type_register_static(&qemu_clk_info);
+}
+
+type_init(qemu_clk_register_types);
-- 
2.5.5




[Qemu-devel] [PATCH V1 02/10] qemu-clk: allow to attach a clock to a device

2016-10-05 Thread fred . konrad
From: KONRAD Frederic 

This allows to attach a clock to a DeviceState.
Contrary to gpios, the clock pins are not contained in the DeviceState but
with the child property so they can appears in the qom-tree.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h | 24 +++-
 qemu-clock.c  | 23 +++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index e7acd68..1d56a2e 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -33,8 +33,30 @@
 typedef struct qemu_clk {
 /*< private >*/
 Object parent_obj;
+char *name;/* name of this clock in the device. */
 } *qemu_clk;
 
-#endif /* QEMU_CLOCK_H */
+/**
+ * qemu_clk_attach_to_device:
+ * @dev: the device on which the clock need to be attached.
+ * @clk: the clock which need to be attached.
+ * @name: the name of the clock can't be NULL.
+ *
+ * Attach @clk named @name to the device @dev.
+ *
+ */
+void qemu_clk_attach_to_device(DeviceState *dev, qemu_clk clk,
+   const char *name);
 
+/**
+ * qemu_clk_get_pin:
+ * @dev: the device which contain the clock.
+ * @name: the name of the clock.
+ *
+ * Get the clock named @name located in the device @dev, or NULL if not found.
+ *
+ * Returns the clock named @name contained in @dev.
+ */
+qemu_clk qemu_clk_get_pin(DeviceState *dev, const char *name);
 
+#endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index ceea98d..0ba6caf 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -25,6 +25,7 @@
 #include "qemu/qemu-clock.h"
 #include "hw/hw.h"
 #include "qemu/log.h"
+#include "qapi/error.h"
 
 #ifndef DEBUG_QEMU_CLOCK
 #define DEBUG_QEMU_CLOCK 0
@@ -36,6 +37,28 @@
 }\
 } while (0);
 
+void qemu_clk_attach_to_device(DeviceState *dev, qemu_clk clk,
+   const char *name)
+{
+assert(name);
+assert(!clk->name);
+object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort);
+clk->name = g_strdup(name);
+}
+
+qemu_clk qemu_clk_get_pin(DeviceState *dev, const char *name)
+{
+gchar *path = NULL;
+Object *clk;
+bool ambiguous;
+
+path = g_strdup_printf("%s/%s", object_get_canonical_path(OBJECT(dev)),
+   name);
+clk = object_resolve_path(path, &ambiguous);
+g_free(path);
+return QEMU_CLOCK(clk);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
2.5.5




[Qemu-devel] [RFC PATCH 04/11] qdev-monitor: print the device's clock with info qtree

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This prints the clock attached to a DeviceState when using "info qtree" monitor
command.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h |  9 +
 qdev-monitor.c|  2 ++
 qemu-clock.c  | 28 
 3 files changed, 39 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index 677de9a..265ec65 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -124,4 +124,13 @@ void qemu_clk_set_callback(qemu_clk clk,
qemu_clk_on_rate_update_cb cb,
void *opaque);
 
+/**
+ * qemu_clk_print:
+ * @dev: the device for which the clock need to be printed.
+ *
+ * Print the clock information for a given device.
+ *
+ */
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qdev-monitor.c b/qdev-monitor.c
index e19617f..d6d1aa4 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -28,6 +28,7 @@
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "qemu/help_option.h"
+#include "qemu/qemu-clock.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -684,6 +685,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int 
indent)
 ngl->num_out);
 }
 }
+qemu_clk_print(mon, dev, indent);
 class = object_get_class(OBJECT(dev));
 do {
 qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
diff --git a/qemu-clock.c b/qemu-clock.c
index 811d6a0..378a14d 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -24,6 +24,7 @@
 #include "qemu/qemu-clock.h"
 #include "hw/hw.h"
 #include "qapi/error.h"
+#include "monitor/monitor.h"
 
 /* #define DEBUG_QEMU_CLOCK */
 
@@ -111,6 +112,33 @@ qemu_clk qemu_clk_get_pin(DeviceState *d, const char *name)
 return QEMU_CLOCK(clk);
 }
 
+struct print_opaque {
+Monitor *mon;
+int indent;
+};
+
+static int qemu_clk_print_rec(Object *obj, void *opaque)
+{
+qemu_clk clk = (qemu_clk)(object_dynamic_cast(obj, TYPE_CLOCK));
+struct print_opaque *po = opaque;
+
+if (clk) {
+monitor_printf(po->mon, "%*s" "qemu-clk \"%s\" %.1f\n", po->indent,
+   " ", clk->name, clk->out_rate);
+}
+
+return 0;
+}
+
+void qemu_clk_print(Monitor *mon, DeviceState *dev, int indent)
+{
+struct print_opaque po;
+
+po.indent = indent;
+po.mon = mon;
+object_child_foreach(OBJECT(dev), qemu_clk_print_rec, &po);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
2.5.5




[Qemu-devel] [RFC PATCH 10/11] zynqmp: add the zynqmp_crf to the platform

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This adds the zynqmp_crf to the zynqmp platform.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 7 +++
 include/hw/arm/xlnx-zynqmp.h | 1 +
 2 files changed, 8 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 4d504da..a8b7669 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -135,6 +135,11 @@ static void xlnx_zynqmp_init(Object *obj)
   TYPE_XILINX_SPIPS);
 qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
 }
+
+s->crf = object_new("xlnx.zynqmp_crf");
+qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
+object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -366,6 +371,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
   &error_abort);
g_free(bus_name);
 }
+
+sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 2332596..78fed6e 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -81,6 +81,7 @@ typedef struct XlnxZynqMPState {
 SysbusAHCIState sata;
 SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
 XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
+Object *crf;
 
 char *boot_cpu;
 ARMCPU *boot_cpu_ptr;
-- 
2.5.5




[Qemu-devel] [RFC PATCH 11/11] zynqmp: add reference clock

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This adds some fixed reference clock to the zynqmp platform.
They will feed the zynqmp_crf block.

Signed-off-by: KONRAD Frederic 
---
 hw/arm/xlnx-zynqmp.c | 42 ++
 include/hw/arm/xlnx-zynqmp.h |  6 ++
 2 files changed, 48 insertions(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index a8b7669..68f924f 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -22,6 +22,7 @@
 #include "hw/arm/xlnx-zynqmp.h"
 #include "hw/intc/arm_gic_common.h"
 #include "exec/address-spaces.h"
+#include "qemu/qemu-clock.h"
 
 #define GIC_NUM_SPI_INTR 160
 
@@ -140,6 +141,22 @@ static void xlnx_zynqmp_init(Object *obj)
 qdev_set_parent_bus(DEVICE(s->crf), sysbus_get_default());
 object_property_add_child(obj, "xlnx.zynqmp_crf", OBJECT(s->crf),
   &error_abort);
+
+s->pss_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_ref_clk", s->pss_ref_clk,
+  &error_abort);
+object_property_set_int(s->pss_ref_clk, 5000, "rate", &error_abort);
+s->video_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "video_clk", s->video_clk, &error_abort);
+object_property_set_int(s->video_clk, 2700, "rate", &error_abort);
+s->pss_alt_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "pss_alt_ref_clk", s->pss_alt_ref_clk,
+  &error_abort);
+s->aux_refclk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "aux_refclk", s->aux_refclk, &error_abort);
+s->gt_crx_ref_clk = object_new(TYPE_FIXED_CLOCK);
+object_property_add_child(obj, "gt_crx_ref_clk", s->gt_crx_ref_clk,
+  &error_abort);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -373,6 +390,31 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 }
 
 sysbus_mmio_map(SYS_BUS_DEVICE(s->crf), 0, 0xFD1A);
+
+/* Bound the clock */
+qemu_clk_bound_clock(qemu_clk_get_pin(DEVICE(s->pss_ref_clk), "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "pss_ref_clk"));
+
+qemu_clk_bound_clock(qemu_clk_get_pin(DEVICE(s->video_clk), "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "video_clk"));
+
+qemu_clk_bound_clock(qemu_clk_get_pin(DEVICE(s->pss_alt_ref_clk),
+  "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "pss_alt_ref_clk"));
+
+qemu_clk_bound_clock(qemu_clk_get_pin(DEVICE(s->aux_refclk), "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "aux_refclk"));
+
+qemu_clk_bound_clock(qemu_clk_get_pin(DEVICE(s->gt_crx_ref_clk),
+  "clk_out"),
+ qemu_clk_get_pin(DEVICE(s->crf), "gt_crx_ref_clk"));
+
+object_property_set_bool(s->crf, true, "realized", &err);
+object_property_set_bool(s->pss_ref_clk, true, "realized", &err);
+object_property_set_bool(s->video_clk, true, "realized", &err);
+object_property_set_bool(s->pss_alt_ref_clk, true, "realized", &err);
+object_property_set_bool(s->aux_refclk, true, "realized", &err);
+object_property_set_bool(s->gt_crx_ref_clk, true, "realized", &err);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 78fed6e..536e4a1 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -26,6 +26,7 @@
 #include "hw/ide/ahci.h"
 #include "hw/sd/sdhci.h"
 #include "hw/ssi/xilinx_spips.h"
+#include "hw/misc/fixed-clock.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
@@ -81,6 +82,11 @@ typedef struct XlnxZynqMPState {
 SysbusAHCIState sata;
 SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
 XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
+Object *pss_ref_clk;
+Object *video_clk;
+Object *pss_alt_ref_clk;
+Object *aux_refclk;
+Object *gt_crx_ref_clk;
 Object *crf;
 
 char *boot_cpu;
-- 
2.5.5




[Qemu-devel] [RFC PATCH 02/11] qemu-clk: allow to attach a clock to a device

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This allows to attach a clock to a DeviceState.
Contrary to gpios, the clock pins are not contained in the DeviceState but
with the child property so they can appears in the qom-tree.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h | 24 +++-
 qemu-clock.c  | 22 ++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index e7acd68..a2ba105 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -33,8 +33,30 @@
 typedef struct qemu_clk {
 /*< private >*/
 Object parent_obj;
+char *name;/* name of this clock in the device. */
 } *qemu_clk;
 
-#endif /* QEMU_CLOCK_H */
+/**
+ * qemu_clk_attach_to_device:
+ * @d: the device on which the clock need to be attached.
+ * @clk: the clock which need to be attached.
+ * @name: the name of the clock can't be NULL.
+ *
+ * Attach @clk named @name to the device @d.
+ *
+ */
+void qemu_clk_attach_to_device(DeviceState *d, qemu_clk clk,
+   const char *name);
 
+/**
+ * qemu_clk_get_pin:
+ * @d: the device which contain the clock.
+ * @name: the name of the clock.
+ *
+ * Get the clock named @name located in the device @d, or NULL if not found.
+ *
+ * Returns the clock named @name contained in @d.
+ */
+qemu_clk qemu_clk_get_pin(DeviceState *d, const char *name);
 
+#endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index 4a47fb4..81f2852 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -23,6 +23,7 @@
 
 #include "qemu/qemu-clock.h"
 #include "hw/hw.h"
+#include "qapi/error.h"
 
 /* #define DEBUG_QEMU_CLOCK */
 
@@ -33,6 +34,27 @@ do { printf("qemu-clock: " fmt , ## __VA_ARGS__); } while (0)
 #define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
+void qemu_clk_attach_to_device(DeviceState *d, qemu_clk clk, const char *name)
+{
+assert(name);
+assert(!clk->name);
+object_property_add_child(OBJECT(d), name, OBJECT(clk), &error_abort);
+clk->name = g_strdup(name);
+}
+
+qemu_clk qemu_clk_get_pin(DeviceState *d, const char *name)
+{
+gchar *path = NULL;
+Object *clk;
+bool ambiguous;
+
+path = g_strdup_printf("%s/%s", object_get_canonical_path(OBJECT(d)),
+   name);
+clk = object_resolve_path(path, &ambiguous);
+g_free(path);
+return QEMU_CLOCK(clk);
+}
+
 static const TypeInfo qemu_clk_info = {
 .name  = TYPE_CLOCK,
 .parent= TYPE_OBJECT,
-- 
2.5.5




[Qemu-devel] [RFC PATCH 07/11] introduce zynqmp_crf

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This introduce Xilinx zynqmp-crf.
It is extracted from the qemu xilinx tree 
(02d2f0203dd489ed30d9c8d90c14a52c57332b25) and is used as
an example for the clock framework.
---
 hw/misc/Makefile.objs   |   1 +
 hw/misc/xilinx_zynqmp_crf.c | 532 
 2 files changed, 533 insertions(+)
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index e8b8855..c6e3c7f 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -44,6 +44,7 @@ obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_ZYNQ) += xlnx-zynqmp-iou-slcr.o
+obj-$(CONFIG_ZYNQ) += xilinx_zynqmp_crf.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
diff --git a/hw/misc/xilinx_zynqmp_crf.c b/hw/misc/xilinx_zynqmp_crf.c
new file mode 100644
index 000..b1bf2a6
--- /dev/null
+++ b/hw/misc/xilinx_zynqmp_crf.c
@@ -0,0 +1,532 @@
+/*
+ * QEMU model of the CRF_APB APB control registers for clock controller. The
+ * RST_ctrl_fpd will be added to this as well
+ *
+ * Copyright (c) 2014 Xilinx Inc.
+ *
+ * Autogenerated by xregqemu.py 2014-01-22.
+ *
+ * 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/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+
+#ifndef XILINX_CRF_APB_ERR_DEBUG
+#define XILINX_CRF_APB_ERR_DEBUG 0
+#endif
+
+#define TYPE_XILINX_CRF_APB "xlnx.zynqmp_crf"
+
+#define XILINX_CRF_APB(obj) \
+ OBJECT_CHECK(CRF_APB, (obj), TYPE_XILINX_CRF_APB)
+
+REG32(ERR_CTRL, 0x0)
+FIELD(ERR_CTRL, SLVERR_ENABLE, 1, 0)
+REG32(IR_STATUS, 0x4)
+FIELD(IR_STATUS, ADDR_DECODE_ERR, 1, 0)
+REG32(IR_MASK, 0x8)
+FIELD(IR_MASK, ADDR_DECODE_ERR, 1, 0)
+REG32(IR_ENABLE, 0xc)
+FIELD(IR_ENABLE, ADDR_DECODE_ERR, 1, 0)
+REG32(IR_DISABLE, 0x10)
+FIELD(IR_DISABLE, ADDR_DECODE_ERR, 1, 0)
+REG32(CRF_ECO, 0x18)
+REG32(APLL_CTRL, 0x20)
+FIELD(APLL_CTRL, POST_SRC, 3, 24)
+FIELD(APLL_CTRL, PRE_SRC, 3, 20)
+FIELD(APLL_CTRL, CLKOUTDIV, 1, 17)
+FIELD(APLL_CTRL, DIV2, 1, 16)
+FIELD(APLL_CTRL, FBDIV, 7, 8)
+FIELD(APLL_CTRL, BYPASS, 1, 3)
+FIELD(APLL_CTRL, RESET, 1, 0)
+REG32(APLL_CFG, 0x24)
+FIELD(APLL_CFG, LOCK_DLY, 7, 25)
+FIELD(APLL_CFG, LOCK_CNT, 10, 13)
+FIELD(APLL_CFG, LFHF, 2, 10)
+FIELD(APLL_CFG, CP, 4, 5)
+FIELD(APLL_CFG, RES, 4, 0)
+REG32(APLL_FRAC_CFG, 0x28)
+FIELD(APLL_FRAC_CFG, ENABLED, 1, 31)
+FIELD(APLL_FRAC_CFG, SEED, 3, 22)
+FIELD(APLL_FRAC_CFG, ALGRTHM, 1, 19)
+FIELD(APLL_FRAC_CFG, ORDER, 1, 18)
+FIELD(APLL_FRAC_CFG, DATA, 16, 0)
+REG32(DPLL_CTRL, 0x2c)
+FIELD(DPLL_CTRL, POST_SRC, 3, 24)
+FIELD(DPLL_CTRL, PRE_SRC, 3, 20)
+FIELD(DPLL_CTRL, CLKOUTDIV, 1, 17)
+FIELD(DPLL_CTRL, DIV2, 1, 16)
+FIELD(DPLL_CTRL, FBDIV, 7, 8)
+FIELD(DPLL_CTRL, BYPASS, 1, 3)
+FIELD(DPLL_CTRL, RESET, 1, 0)
+REG32(DPLL_CFG, 0x30)
+FIELD(DPLL_CFG, LOCK_DLY, 7, 25)
+FIELD(DPLL_CFG, LOCK_CNT, 10, 13)
+FIELD(DPLL_CFG, LFHF, 2, 10)
+FIELD(DPLL_CFG, CP, 4, 5)
+FIELD(DPLL_CFG, RES, 4, 0)
+REG32(DPLL_FRAC_CFG, 0x34)
+FIELD(DPLL_FRAC_CFG, ENABLED, 1, 31)
+FIELD(DPLL_FRAC_CFG, SEED, 3, 22)
+FIELD(DPLL_FRAC_CFG, ALGRTHM, 1, 19)
+FIELD(DPLL_FRAC_CFG, ORDER, 1, 18)
+FIELD(DPLL_FRAC_CFG, DATA, 16, 0)
+REG32(VPLL_CTRL, 0x38)
+FIELD(VPLL_CTRL, POST_SRC, 3, 24)
+FIELD(VPLL_CTRL, PRE_SRC, 3, 20)
+FIELD(VPLL_CTRL, CLKOUTDIV, 1, 17)
+FIELD(VPLL_CTRL, DIV2, 1, 16)
+FIELD(VPLL_CTRL, FBDIV, 7, 8)
+FIELD(VPLL_CTRL, BYPASS, 1, 3)
+FIELD(VPLL_CTRL, RESET, 1, 0)
+REG32(VPLL_CFG, 0x3c)
+FIELD(VPLL_CFG, LOCK_DLY, 7, 25)
+FIELD(VPLL_CFG, LOCK_CNT, 10, 13)
+FIELD(VPLL_CFG, LFHF, 2, 10)
+FIELD(VPLL_CFG, CP, 4, 5)
+FIELD(VPLL_CFG, RES, 4, 0)
+REG32(V

[Qemu-devel] [RFC PATCH 09/11] zynqmp_crf: add the clock mechanism

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This adds the pll to the zynqmp_crf and the dp_video clock output.

Signed-off-by: KONRAD Frederic 
---
 hw/misc/xilinx_zynqmp_crf.c | 440 
 1 file changed, 440 insertions(+)

diff --git a/hw/misc/xilinx_zynqmp_crf.c b/hw/misc/xilinx_zynqmp_crf.c
index 4c670a0..2097534 100644
--- a/hw/misc/xilinx_zynqmp_crf.c
+++ b/hw/misc/xilinx_zynqmp_crf.c
@@ -30,6 +30,7 @@
 #include "hw/register.h"
 #include "qemu/bitops.h"
 #include "qemu/log.h"
+#include "qemu/qemu-clock.h"
 
 #ifndef XILINX_CRF_APB_ERR_DEBUG
 #define XILINX_CRF_APB_ERR_DEBUG 0
@@ -281,6 +282,38 @@ typedef struct CRF_APB {
 
 uint32_t regs[R_MAX];
 RegisterInfo regs_info[R_MAX];
+
+/* input clocks */
+qemu_clk pss_ref_clk;
+qemu_clk video_clk;
+qemu_clk pss_alt_ref_clk;
+qemu_clk aux_refclk;
+qemu_clk gt_crx_ref_clk;
+
+/* internal clocks */
+qemu_clk apll_clk;
+qemu_clk dpll_clk;
+qemu_clk vpll_clk;
+
+/* output clocks */
+qemu_clk acpu_clk;
+qemu_clk dbg_trace;
+qemu_clk dbg_fdp;
+qemu_clk dp_video_ref;
+qemu_clk dp_audio_ref;
+qemu_clk dp_stc_ref;
+qemu_clk ddr;
+qemu_clk gpu_ref;
+qemu_clk sata_ref;
+qemu_clk pcie_ref;
+qemu_clk gdma_ref;
+qemu_clk dpdma_ref;
+qemu_clk topsw_main;
+qemu_clk topsw_lsbus;
+qemu_clk dbg_tstmp;
+qemu_clk apll_to_lpd;
+qemu_clk dpll_to_lpd;
+qemu_clk vpll_to_lpd;
 } CRF_APB;
 
 static const MemoryRegionOps crf_apb_ops = {
@@ -325,6 +358,318 @@ static uint64_t ir_disable_prew(RegisterInfo *reg, 
uint64_t val64)
 return 0;
 }
 
+enum clk_src {
+VIDEO_CLK = 4,
+PSS_ALT_REF_CLK = 5,
+AUX_REF_CLK = 6,
+GT_CRX_REF_CLK = 7,
+PSS_REF_CLK = 0
+};
+
+static void apll_to_lpd_postw(RegisterInfo *reg, uint64_t val64)
+{
+CRF_APB *s = XILINX_CRF_APB(reg->opaque);
+
+qemu_clk_refresh(s->apll_to_lpd);
+}
+
+static float apll_to_lpd_update_rate(void *opaque, float input_rate)
+{
+CRF_APB *s = XILINX_CRF_APB(opaque);
+uint32_t divisor = AF_EX32(s->regs, APLL_TO_LPD_CTRL, DIVISOR0);
+
+if (!divisor) {
+return 0.0f;
+} else {
+return input_rate / (float)divisor;
+}
+}
+
+static void dpll_to_lpd_postw(RegisterInfo *reg, uint64_t val64)
+{
+CRF_APB *s = XILINX_CRF_APB(reg->opaque);
+
+qemu_clk_refresh(s->dpll_to_lpd);
+}
+
+static float dpll_to_lpd_update_rate(void *opaque, float input_rate)
+{
+CRF_APB *s = XILINX_CRF_APB(opaque);
+uint32_t divisor = AF_EX32(s->regs, DPLL_TO_LPD_CTRL, DIVISOR0);
+
+if (!divisor) {
+return 0.0f;
+} else {
+return input_rate / (float)divisor;
+}
+}
+
+static void vpll_to_lpd_postw(RegisterInfo *reg, uint64_t val64)
+{
+CRF_APB *s = XILINX_CRF_APB(reg->opaque);
+
+qemu_clk_refresh(s->vpll_to_lpd);
+}
+
+static float vpll_to_lpd_update_rate(void *opaque, float input_rate)
+{
+CRF_APB *s = XILINX_CRF_APB(opaque);
+uint32_t divisor = AF_EX32(s->regs, VPLL_TO_LPD_CTRL, DIVISOR0);
+
+if (!divisor) {
+return 0.0f;
+} else {
+return input_rate / (float)divisor;
+}
+}
+
+static void apll_ctrl_postw(RegisterInfo *reg, uint64_t val64)
+{
+CRF_APB *s = XILINX_CRF_APB(reg->opaque);
+uint32_t source = AF_EX32(s->regs, APLL_CTRL, BYPASS)
+? AF_EX32(s->regs, APLL_CTRL, POST_SRC)
+: AF_EX32(s->regs, APLL_CTRL, PRE_SRC);
+
+/*
+ * We must ensure that only one clock is bound to the apll internal clock.
+ */
+qemu_clk_unbound(s->pss_ref_clk, s->apll_clk);
+qemu_clk_unbound(s->video_clk, s->apll_clk);
+qemu_clk_unbound(s->pss_alt_ref_clk, s->apll_clk);
+qemu_clk_unbound(s->aux_refclk, s->apll_clk);
+qemu_clk_unbound(s->gt_crx_ref_clk, s->apll_clk);
+
+switch (source) {
+case VIDEO_CLK:
+qemu_clk_bound_clock(s->video_clk, s->apll_clk);
+break;
+case PSS_ALT_REF_CLK:
+qemu_clk_bound_clock(s->pss_alt_ref_clk, s->apll_clk);
+break;
+case AUX_REF_CLK:
+qemu_clk_bound_clock(s->aux_refclk, s->apll_clk);
+break;
+case GT_CRX_REF_CLK:
+qemu_clk_bound_clock(s->gt_crx_ref_clk, s->apll_clk);
+break;
+default:
+qemu_clk_bound_clock(s->pss_ref_clk, s->apll_clk);
+break;
+}
+}
+
+static void dpll_ctrl_postw(RegisterInfo *reg, uint64_t val64)
+{
+CRF_APB *s = XILINX_CRF_APB(reg->opaque);
+uint32_t source = AF_EX32(s->regs, DPLL_CTRL, BYPASS)
+? AF_EX32(s->regs, DPLL_CTRL, POST_SRC)
+: AF_EX32(s->regs, DPLL_CTRL, PRE_SRC);
+
+/*
+ * We must ensure that only one clock is bound to the dpll internal clock.
+ */
+qemu_clk_unbound(s->pss_ref_clk, s->dpll_clk);
+qemu_clk_unbound(s->video_clk, s->dpll_clk);
+qemu_clk_unbound(s->pss_alt_ref_clk, s->dpll_clk);
+qemu_clk_unbound(s->aux_refclk, s->dpll_clk);
+qemu_clk_unbound(s->gt_crx_ref_clk, s->dpl

[Qemu-devel] [RFC PATCH 03/11] qemu-clk: allow to bound two clocks together

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This introduces the clock binding and the update part.
When the qemu_clk_rate_update(qemu_clk, int) function is called:
  * The clock callback is called on the qemu_clk so it can change the rate.
  * The qemu_clk_rate_update function is called on all the driven clock.

Signed-off-by: KONRAD Frederic 
---
 include/qemu/qemu-clock.h | 65 +++
 qemu-clock.c  | 56 
 2 files changed, 121 insertions(+)

diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
index a2ba105..677de9a 100644
--- a/include/qemu/qemu-clock.h
+++ b/include/qemu/qemu-clock.h
@@ -27,15 +27,29 @@
 #include "qemu/osdep.h"
 #include "qom/object.h"
 
+typedef float (*qemu_clk_on_rate_update_cb)(void *opaque, float rate);
+
 #define TYPE_CLOCK "qemu-clk"
 #define QEMU_CLOCK(obj) OBJECT_CHECK(struct qemu_clk, (obj), TYPE_CLOCK)
 
+typedef struct ClkList ClkList;
+
 typedef struct qemu_clk {
 /*< private >*/
 Object parent_obj;
 char *name;/* name of this clock in the device. */
+float in_rate; /* rate of the clock which drive this pin. */
+float out_rate;/* rate of this clock pin. */
+void *opaque;
+qemu_clk_on_rate_update_cb cb;
+QLIST_HEAD(, ClkList) bound;
 } *qemu_clk;
 
+struct ClkList {
+qemu_clk clk;
+QLIST_ENTRY(ClkList) node;
+};
+
 /**
  * qemu_clk_attach_to_device:
  * @d: the device on which the clock need to be attached.
@@ -59,4 +73,55 @@ void qemu_clk_attach_to_device(DeviceState *d, qemu_clk clk,
  */
 qemu_clk qemu_clk_get_pin(DeviceState *d, const char *name);
 
+/**
+ * qemu_clk_bound_clock:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Connect the clock together. This is unidirectionnal so a
+ * qemu_clk_update_rate will go from @out to @in.
+ *
+ */
+void qemu_clk_bound_clock(qemu_clk out, qemu_clk in);
+
+/**
+ * qemu_clk_unbound:
+ * @out: the clock output.
+ * @in: the clock input.
+ *
+ * Disconnect the clock if they were bound together.
+ *
+ */
+void qemu_clk_unbound(qemu_clk out, qemu_clk in);
+
+/**
+ * qemu_clk_update_rate:
+ * @clk: the clock to update.
+ * @rate: the new rate.
+ *
+ * Update the @clk to the new @rate.
+ *
+ */
+void qemu_clk_update_rate(qemu_clk clk, float rate);
+
+/**
+ * qemu_clk_refresh:
+ * @clk: the clock to be refreshed.
+ *
+ * This updates all childs of a clock without changing its own rate.
+ *
+ */
+void qemu_clk_refresh(qemu_clk clk);
+
+/**
+ * qemu_clk_set_callback:
+ * @clk: the clock where to set the callback.
+ * @cb: the callback to associate to the callback.
+ * @opaque: the opaque data passed to the calback.
+ *
+ */
+void qemu_clk_set_callback(qemu_clk clk,
+   qemu_clk_on_rate_update_cb cb,
+   void *opaque);
+
 #endif /* QEMU_CLOCK_H */
diff --git a/qemu-clock.c b/qemu-clock.c
index 81f2852..811d6a0 100644
--- a/qemu-clock.c
+++ b/qemu-clock.c
@@ -34,6 +34,62 @@ do { printf("qemu-clock: " fmt , ## __VA_ARGS__); } while (0)
 #define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
+void qemu_clk_refresh(qemu_clk clk)
+{
+qemu_clk_update_rate(clk, clk->in_rate);
+}
+
+void qemu_clk_update_rate(qemu_clk clk, float rate)
+{
+ClkList *child;
+
+clk->in_rate = rate;
+clk->out_rate = rate;
+
+if (clk->cb) {
+clk->out_rate = clk->cb(clk->opaque, rate);
+}
+
+DPRINTF("%s output rate updated to %.1f\n",
+object_get_canonical_path(OBJECT(clk)),
+clk->out_rate);
+
+QLIST_FOREACH(child, &clk->bound, node) {
+qemu_clk_update_rate(child->clk, clk->out_rate);
+}
+}
+
+void qemu_clk_bound_clock(qemu_clk out, qemu_clk in)
+{
+ClkList *child;
+
+child = g_malloc(sizeof(child));
+assert(child);
+child->clk = in;
+QLIST_INSERT_HEAD(&out->bound, child, node);
+qemu_clk_update_rate(in, out->out_rate);
+}
+
+void qemu_clk_unbound(qemu_clk out, qemu_clk in)
+{
+ClkList *child, *next;
+
+QLIST_FOREACH_SAFE(child, &out->bound, node, next) {
+if (child->clk == in) {
+QLIST_REMOVE(child, node);
+g_free(child);
+}
+}
+}
+
+void qemu_clk_set_callback(qemu_clk clk,
+   qemu_clk_on_rate_update_cb cb,
+   void *opaque)
+{
+clk->cb = cb;
+clk->opaque = opaque;
+}
+
 void qemu_clk_attach_to_device(DeviceState *d, qemu_clk clk, const char *name)
 {
 assert(name);
-- 
2.5.5




[Qemu-devel] [RFC PATCH 08/11] zynqmp_crf: fix against AF_EX32 changes

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This seems to be due to a difference between the AF_EX32 define.

Signed-off-by: KONRAD Frederic 
---
 hw/misc/xilinx_zynqmp_crf.c | 354 ++--
 1 file changed, 177 insertions(+), 177 deletions(-)

diff --git a/hw/misc/xilinx_zynqmp_crf.c b/hw/misc/xilinx_zynqmp_crf.c
index b1bf2a6..4c670a0 100644
--- a/hw/misc/xilinx_zynqmp_crf.c
+++ b/hw/misc/xilinx_zynqmp_crf.c
@@ -41,236 +41,236 @@
  OBJECT_CHECK(CRF_APB, (obj), TYPE_XILINX_CRF_APB)
 
 REG32(ERR_CTRL, 0x0)
-FIELD(ERR_CTRL, SLVERR_ENABLE, 1, 0)
+FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
 REG32(IR_STATUS, 0x4)
-FIELD(IR_STATUS, ADDR_DECODE_ERR, 1, 0)
+FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
 REG32(IR_MASK, 0x8)
-FIELD(IR_MASK, ADDR_DECODE_ERR, 1, 0)
+FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
 REG32(IR_ENABLE, 0xc)
-FIELD(IR_ENABLE, ADDR_DECODE_ERR, 1, 0)
+FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
 REG32(IR_DISABLE, 0x10)
-FIELD(IR_DISABLE, ADDR_DECODE_ERR, 1, 0)
+FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
 REG32(CRF_ECO, 0x18)
 REG32(APLL_CTRL, 0x20)
-FIELD(APLL_CTRL, POST_SRC, 3, 24)
-FIELD(APLL_CTRL, PRE_SRC, 3, 20)
-FIELD(APLL_CTRL, CLKOUTDIV, 1, 17)
-FIELD(APLL_CTRL, DIV2, 1, 16)
-FIELD(APLL_CTRL, FBDIV, 7, 8)
-FIELD(APLL_CTRL, BYPASS, 1, 3)
-FIELD(APLL_CTRL, RESET, 1, 0)
+FIELD(APLL_CTRL, POST_SRC, 24, 3)
+FIELD(APLL_CTRL, PRE_SRC, 20, 3)
+FIELD(APLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(APLL_CTRL, DIV2, 16, 1)
+FIELD(APLL_CTRL, FBDIV, 8, 7)
+FIELD(APLL_CTRL, BYPASS, 3, 1)
+FIELD(APLL_CTRL, RESET, 0, 1)
 REG32(APLL_CFG, 0x24)
-FIELD(APLL_CFG, LOCK_DLY, 7, 25)
-FIELD(APLL_CFG, LOCK_CNT, 10, 13)
-FIELD(APLL_CFG, LFHF, 2, 10)
-FIELD(APLL_CFG, CP, 4, 5)
-FIELD(APLL_CFG, RES, 4, 0)
+FIELD(APLL_CFG, LOCK_DLY, 25, 7)
+FIELD(APLL_CFG, LOCK_CNT, 13, 10)
+FIELD(APLL_CFG, LFHF, 10, 2)
+FIELD(APLL_CFG, CP, 5, 4)
+FIELD(APLL_CFG, RES, 0, 4)
 REG32(APLL_FRAC_CFG, 0x28)
-FIELD(APLL_FRAC_CFG, ENABLED, 1, 31)
-FIELD(APLL_FRAC_CFG, SEED, 3, 22)
-FIELD(APLL_FRAC_CFG, ALGRTHM, 1, 19)
-FIELD(APLL_FRAC_CFG, ORDER, 1, 18)
-FIELD(APLL_FRAC_CFG, DATA, 16, 0)
+FIELD(APLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(APLL_FRAC_CFG, SEED, 22, 3)
+FIELD(APLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(APLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(APLL_FRAC_CFG, DATA, 0, 16)
 REG32(DPLL_CTRL, 0x2c)
-FIELD(DPLL_CTRL, POST_SRC, 3, 24)
-FIELD(DPLL_CTRL, PRE_SRC, 3, 20)
-FIELD(DPLL_CTRL, CLKOUTDIV, 1, 17)
-FIELD(DPLL_CTRL, DIV2, 1, 16)
-FIELD(DPLL_CTRL, FBDIV, 7, 8)
-FIELD(DPLL_CTRL, BYPASS, 1, 3)
-FIELD(DPLL_CTRL, RESET, 1, 0)
+FIELD(DPLL_CTRL, POST_SRC, 24, 3)
+FIELD(DPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(DPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(DPLL_CTRL, DIV2, 16, 1)
+FIELD(DPLL_CTRL, FBDIV, 8, 7)
+FIELD(DPLL_CTRL, BYPASS, 3, 1)
+FIELD(DPLL_CTRL, RESET, 0, 1)
 REG32(DPLL_CFG, 0x30)
-FIELD(DPLL_CFG, LOCK_DLY, 7, 25)
-FIELD(DPLL_CFG, LOCK_CNT, 10, 13)
-FIELD(DPLL_CFG, LFHF, 2, 10)
-FIELD(DPLL_CFG, CP, 4, 5)
-FIELD(DPLL_CFG, RES, 4, 0)
+FIELD(DPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(DPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(DPLL_CFG, LFHF, 10, 2)
+FIELD(DPLL_CFG, CP, 5, 4)
+FIELD(DPLL_CFG, RES, 0, 4)
 REG32(DPLL_FRAC_CFG, 0x34)
-FIELD(DPLL_FRAC_CFG, ENABLED, 1, 31)
-FIELD(DPLL_FRAC_CFG, SEED, 3, 22)
-FIELD(DPLL_FRAC_CFG, ALGRTHM, 1, 19)
-FIELD(DPLL_FRAC_CFG, ORDER, 1, 18)
-FIELD(DPLL_FRAC_CFG, DATA, 16, 0)
+FIELD(DPLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(DPLL_FRAC_CFG, SEED, 22, 3)
+FIELD(DPLL_FRAC_CFG, ALGRTHM, 19, 1)
+FIELD(DPLL_FRAC_CFG, ORDER, 18, 1)
+FIELD(DPLL_FRAC_CFG, DATA, 0, 16)
 REG32(VPLL_CTRL, 0x38)
-FIELD(VPLL_CTRL, POST_SRC, 3, 24)
-FIELD(VPLL_CTRL, PRE_SRC, 3, 20)
-FIELD(VPLL_CTRL, CLKOUTDIV, 1, 17)
-FIELD(VPLL_CTRL, DIV2, 1, 16)
-FIELD(VPLL_CTRL, FBDIV, 7, 8)
-FIELD(VPLL_CTRL, BYPASS, 1, 3)
-FIELD(VPLL_CTRL, RESET, 1, 0)
+FIELD(VPLL_CTRL, POST_SRC, 24, 3)
+FIELD(VPLL_CTRL, PRE_SRC, 20, 3)
+FIELD(VPLL_CTRL, CLKOUTDIV, 17, 1)
+FIELD(VPLL_CTRL, DIV2, 16, 1)
+FIELD(VPLL_CTRL, FBDIV, 8, 7)
+FIELD(VPLL_CTRL, BYPASS, 3, 1)
+FIELD(VPLL_CTRL, RESET, 0, 1)
 REG32(VPLL_CFG, 0x3c)
-FIELD(VPLL_CFG, LOCK_DLY, 7, 25)
-FIELD(VPLL_CFG, LOCK_CNT, 10, 13)
-FIELD(VPLL_CFG, LFHF, 2, 10)
-FIELD(VPLL_CFG, CP, 4, 5)
-FIELD(VPLL_CFG, RES, 4, 0)
+FIELD(VPLL_CFG, LOCK_DLY, 25, 7)
+FIELD(VPLL_CFG, LOCK_CNT, 13, 10)
+FIELD(VPLL_CFG, LFHF, 10, 2)
+FIELD(VPLL_CFG, CP, 5, 4)
+FIELD(VPLL_CFG, RES, 0, 4)
 REG32(VPLL_FRAC_CFG, 0x40)
-FIELD(VPLL_FRAC_CFG, ENABLED, 1, 31)
-FIELD(VPLL_FRAC_CFG, SEED, 3, 22)
-FIELD(VPLL_FRAC_CFG, ALGRTHM, 1, 19)
-FIELD(VPLL_FRAC_CFG, ORDER, 1, 18)
-FIELD(VPLL_FRAC_CFG, DATA, 16, 0)
+FIELD(VPLL_FRAC_CFG, ENABLED, 31, 1)
+FIELD(VPLL_FRAC_CFG, SEED, 22, 3)
+   

[Qemu-devel] [RFC PATCH 00/11] Clock framework API.

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

Hi,

This is a first draft of the clock framework API it contains:

  * The first 5 patches which introduce the framework.
  * The 6th patch which introduces a fixed-clock model.
  * The rest which gives an example how to model a PLL from the existing
zynqmp-crf extracted from the qemu xilinx tree.

No specific behavior is expected yet when the CRF register set is accessed but
the user can see for example the dp_video_ref and vpll_to_lpd rate changing in
the monitor with the "info qtree" command when the vpll_ctrl register is
modified.

bus: main-system-bus
  type System
  dev: xlnx.zynqmp_crf, id ""
gpio-out "sysbus-irq" 1
gpio-out "RST_A9" 4
qemu-clk "dbg_trace" 0.0
qemu-clk "vpll_to_lpd" 1250.0
qemu-clk "dp_stc_ref" 0.0
qemu-clk "dpll_to_lpd" 1250.0
qemu-clk "acpu_clk" 0.0
qemu-clk "pcie_ref" 0.0
qemu-clk "topsw_main" 0.0
qemu-clk "topsw_lsbus" 0.0
qemu-clk "dp_audio_ref" 0.0
qemu-clk "sata_ref" 0.0
qemu-clk "dp_video_ref" 1428571.4
qemu-clk "vpll_clk" 5000.0
qemu-clk "apll_to_lpd" 1250.0
qemu-clk "dpll_clk" 5000.0
qemu-clk "gpu_ref" 0.0
qemu-clk "aux_refclk" 0.0
qemu-clk "video_clk" 2700.0
qemu-clk "gdma_ref" 0.0
qemu-clk "gt_crx_ref_clk" 0.0
qemu-clk "dbg_fdp" 0.0
qemu-clk "apll_clk" 5000.0
qemu-clk "pss_alt_ref_clk" 0.0
qemu-clk "ddr" 0.0
qemu-clk "pss_ref_clk" 5000.0
qemu-clk "dpdma_ref" 0.0
qemu-clk "dbg_tstmp" 0.0
mmio fd1a/010c

This series is based on the current master
(d6550e9ed2e1a60d889dfb721de00d9a4e3bafbe) with the data-driven register
patch-set from Alistair.

Note that the omap clock infrastructure is really far from what we need so I
think it's worse implement the clock framework and then rework the omaps
platforms to use it.

TODO:
  * reshape the omap clock tree to use this one.

Any comment on that?

Thanks,
Fred

KONRAD Frederic (11):
  qemu-clk: introduce qemu-clk qom object
  qemu-clk: allow to attach a clock to a device
  qemu-clk: allow to bound two clocks together
  qdev-monitor: print the device's clock with info qtree
  docs: add qemu-clock documentation
  introduce fixed-clock
  introduce zynqmp_crf
  zynqmp_crf: fix against AF_EX32 changes
  zynqmp_crf: add the clock mechanism
  zynqmp: add the zynqmp_crf to the platform
  zynqmp: add reference clock

 Makefile.objs |   1 +
 docs/clock.txt| 112 +
 hw/arm/xlnx-zynqmp.c  |  49 +++
 hw/misc/Makefile.objs |   3 +
 hw/misc/fixed-clock.c |  87 
 hw/misc/xilinx_zynqmp_crf.c   | 972 ++
 include/hw/arm/xlnx-zynqmp.h  |   7 +
 include/hw/misc/fixed-clock.h |  30 ++
 include/qemu/qemu-clock.h | 136 ++
 qdev-monitor.c|   2 +
 qemu-clock.c  | 153 +++
 11 files changed, 1552 insertions(+)
 create mode 100644 docs/clock.txt
 create mode 100644 hw/misc/fixed-clock.c
 create mode 100644 hw/misc/xilinx_zynqmp_crf.c
 create mode 100644 include/hw/misc/fixed-clock.h
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

-- 
2.5.5




[Qemu-devel] [RFC PATCH 01/11] qemu-clk: introduce qemu-clk qom object

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This introduces qemu-clk qom object.

Signed-off-by: KONRAD Frederic 
---
 Makefile.objs |  1 +
 include/qemu/qemu-clock.h | 40 
 qemu-clock.c  | 47 +++
 3 files changed, 88 insertions(+)
 create mode 100644 include/qemu/qemu-clock.h
 create mode 100644 qemu-clock.c

diff --git a/Makefile.objs b/Makefile.objs
index 61f4bf4..2284ef5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -77,6 +77,7 @@ common-obj-y += backends/
 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
 
 common-obj-$(CONFIG_FDT) += device_tree.o
+common-obj-y += qemu-clock.o
 
 ##
 # qapi
diff --git a/include/qemu/qemu-clock.h b/include/qemu/qemu-clock.h
new file mode 100644
index 000..e7acd68
--- /dev/null
+++ b/include/qemu/qemu-clock.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#ifndef QEMU_CLOCK_H
+#define QEMU_CLOCK_H
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+
+#define TYPE_CLOCK "qemu-clk"
+#define QEMU_CLOCK(obj) OBJECT_CHECK(struct qemu_clk, (obj), TYPE_CLOCK)
+
+typedef struct qemu_clk {
+/*< private >*/
+Object parent_obj;
+} *qemu_clk;
+
+#endif /* QEMU_CLOCK_H */
+
+
diff --git a/qemu-clock.c b/qemu-clock.c
new file mode 100644
index 000..4a47fb4
--- /dev/null
+++ b/qemu-clock.c
@@ -0,0 +1,47 @@
+/*
+ * QEMU Clock
+ *
+ *  Copyright (C) 2016 : GreenSocs Ltd
+ *  http://www.greensocs.com/ , email: i...@greensocs.com
+ *
+ *  Frederic Konrad 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ *
+ */
+
+#include "qemu/qemu-clock.h"
+#include "hw/hw.h"
+
+/* #define DEBUG_QEMU_CLOCK */
+
+#ifdef DEBUG_QEMU_CLOCK
+#define DPRINTF(fmt, ...) \
+do { printf("qemu-clock: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+static const TypeInfo qemu_clk_info = {
+.name  = TYPE_CLOCK,
+.parent= TYPE_OBJECT,
+.instance_size = sizeof(struct qemu_clk),
+};
+
+static void qemu_clk_register_types(void)
+{
+type_register_static(&qemu_clk_info);
+}
+
+type_init(qemu_clk_register_types);
-- 
2.5.5




[Qemu-devel] [RFC PATCH 05/11] docs: add qemu-clock documentation

2016-06-13 Thread fred . konrad
From: KONRAD Frederic 

This adds the qemu-clock documentation.

Signed-off-by: KONRAD Frederic 
---
 docs/clock.txt | 112 +
 1 file changed, 112 insertions(+)
 create mode 100644 docs/clock.txt

diff --git a/docs/clock.txt b/docs/clock.txt
new file mode 100644
index 000..f4ad4c8
--- /dev/null
+++ b/docs/clock.txt
@@ -0,0 +1,112 @@
+
+What is a QEMU_CLOCK
+
+
+A QEMU_CLOCK is a QOM Object developed for the purpose of modeling a clock tree
+with QEMU.
+
+It only simulates the clock by keeping a copy of the current frequency and
+doesn't model the signal itself such as pin toggle or duty cycle.
+
+It allows to model the impact of badly configured PLL, clock source selection
+or disabled clock on the models.
+
+Bounding the clock together to create a tree
+
+
+In order to create a clock tree with QEMU_CLOCK two or more clock must be bound
+together. Let's say there are two clocks clk_a and clk_b:
+Using qemu_clk_bound(clk_a, clk_b) will bound clk_a and clk_b.
+
+Binding two qemu-clk together is a unidirectional link which means that 
changing
+the rate of clk_a will propagate to clk_b and not the opposite. The bound
+process automatically refresh clk_b rate.
+
+Clock can be bound and unbound during execution for modeling eg: a clock
+selector.
+
+A clock can drive more than one other clock. eg with this code:
+qemu_clk_bound(clk_a, clk_b);
+qemu_clk_bound(clk_a, clk_c);
+
+A clock rate change one clk_a will propagate to clk_b and clk_c.
+
+Implementing a callback on a rate change
+
+
+The function prototype is the following:
+typedef float (*qemu_clk_rate_change_cb)(void *opaque, float rate);
+
+It's main goal is to modify the rate before it's passed to the next clocks in
+the tree.
+
+eg: for a 4x PLL the function will be:
+float qemu_clk_rate_change_cb(void *opaque, float rate)
+{
+return 4.0 * rate;
+}
+
+To set the callback for the clock:
+void qemu_clk_set_callback(qemu_clk clk, qemu_clk_on_rate_update_cb cb,
+   void *opaque);
+can be called.
+
+NOTE: It's not recommended that the clock is driven by more than one clock as 
it
+would mean that we don't know which clock trigger the callback.
+
+The rate update process
+===
+
+The rate update happen in this way:
+When a model wants to update a clock frequency (eg: based on a register change
+or something similar) it will call qemu_clk_update_rate(..) on the clock:
+  * The callback associated to the clock is called with the new rate.
+  * qemu_clk_update_rate(..) is then called on all bound clock with the
+value returned by the callback.
+
+NOTE: When no callback is attached the clock qemu_clk_update_rate(..) is called
+with the unmodified rate.
+
+Attaching a QEMU_CLOCK to a DeviceState
+===
+
+Attaching a qemu-clk to a DeviceState is required to be able to get the clock
+outside the model through qemu_clk_get_pin(..).
+
+It is also required to be able to print the clock and its rate with info qtree.
+For example:
+
+  type System
+  dev: xlnx.zynqmp_crf, id ""
+gpio-out "sysbus-irq" 1
+gpio-out "RST_A9" 4
+qemu-clk "dbg_trace" 0.0
+qemu-clk "vpll_to_lpd" 62500.0
+qemu-clk "dp_stc_ref" 0.0
+qemu-clk "dpll_to_lpd" 1250.0
+qemu-clk "acpu_clk" 0.0
+qemu-clk "pcie_ref" 0.0
+qemu-clk "topsw_main" 0.0
+qemu-clk "topsw_lsbus" 0.0
+qemu-clk "dp_audio_ref" 0.0
+qemu-clk "sata_ref" 0.0
+qemu-clk "dp_video_ref" 71428568.0
+qemu-clk "vpll_clk" 25.0
+qemu-clk "apll_to_lpd" 1250.0
+qemu-clk "dpll_clk" 5000.0
+qemu-clk "gpu_ref" 0.0
+qemu-clk "aux_refclk" 0.0
+qemu-clk "video_clk" 2700.0
+qemu-clk "gdma_ref" 0.0
+qemu-clk "gt_crx_ref_clk" 0.0
+qemu-clk "dbg_fdp" 0.0
+qemu-clk "apll_clk" 5000.0
+qemu-clk "pss_alt_ref_clk" 0.0
+qemu-clk "ddr" 0.0
+qemu-clk "pss_ref_clk" 5000.0
+qemu-clk "dpdma_ref" 0.0
+qemu-clk "dbg_tstmp" 0.0
+mmio fd1a/010c
+
+This way a DeviceState can have multiple clock input or output.
+
-- 
2.5.5




  1   2   3   4   5   6   7   8   >