2016/09/24

Log of A Linux Hacking Project

Some notes about interrupt handling:
- Device tree configuration file has information about a peripherals's HW irq number
- IRQ chip driver do below:
  - maps HW irq number to software irq number
  - find out which HW irq is raised
- Peripheral driver find out which software irq this device is associated with, and a interrupt handler is registered.

===================================================
DRAM offset/size configuration and image relocation 
  Start up code of the zImage.
  setup page table
  get size of decompressed kernel size at the end of the compressed data
  relocate the zImage code
  setup BSS
  setup stack (due to DRAM bug, stack is put on SPM)
  jump to decompress_kernel (in Misc.c)
  setup MMU mapping, hard coded mapping for DRAM area
  turn on cachable and bufferable for DRAM
===================================================
/arch/arm/boot/compressed/head.S

#define HELIOSX_DRAM_REGION_BASE   (CONFIG_HELIOSX_DRAM_REGION_BASE)

#define HELIOSX_DRAM_SIZE  (0x08000000)  // 128M
#define HELIOSX_DRAM_START (HELIOSX_DRAM_REGION_BASE + 0x08000000)
#define HELIOSX_DRAM_END   (HELIOSX_DRAM_START + HELIOSX_DRAM_SIZE)
#define HELIOSX_ZRELADDR   (HELIOSX_DRAM_START + TEXT_OFFSET)
...

/* xgu hack, just set MMU to map all the RAM between 0x08000000 - 0x10000000
 *   everything is hardcoded
 *   r4 = 0x0a000000
 *   r3 = 0x09f00000
 */
__setup_mmu_heliosx:
  @sub r3, r4, #0x00100000 @ 1M for Page directory, to place 170000, not ok
  @mov r3, #0x1b000000  @ hard code to a place
  add     r3, r4, #0x00800000     @ Add 8M offset to 0x08000000

  mov r0, r3   @ table of index
  mov r9,  #HELIOSX_DRAM_START @ start of RAM
  mov  r10, #HELIOSX_DRAM_END  @ end of RAM
  mov r1, #0x12  @ section mapping
  orr r1, r1, #3 << 10 @ AP=11
...

===================================================
Utility to output number 
  MMU setting, remapping
===================================================
/arch/arm/boot/compressed/misc.c
static void putNum(uint32_t num)
...


===================================================
Configuration related
===================================================
/arch/arm/Makefile
machine-$(CONFIG_ARCH_HELIOSX)  += heliosx

/arch/arm/boot/dts/Makefile
dtb-$(CONFIG_ARCH_HELIOSX) += heliosx.dtb

/arch/arm/tools/mach-types
heliosx            MACH_HELIOSX        HELIOSX            7777


===================================================
device tree configuration
  memory 
  interrupt controller
  timer (interrupts = <8>)
  UART, serial port  (interrupts = <2>;)
===================================================
/arch/arm/boot/dts/heliosx.dts

 memory{
  device_type = "memory";
  reg = <0x08000000 0x04000000="">;
 };

 soc {
  compatible = "simple-bus"; /* mapping to platform bus*/
  #address-cells = <1>;
  #size-cells = <1>;
  ranges;

  intc_legacy: intc@D0081000 {
   compatible = "arm,heliosx-intc-legacy";
   interrupt-controller;
   #interrupt-cells = <1>;
  
  // other peripherals, register memory map and physical interrupt number ...  
    timer@D0081200 {
   compatible = "arm,heliosx-timer";
   reg = <0xd0081200 0x100="">;
   interrupts = <8>;
   clock-names = "heliosx-timer";
  };

  serial0: serial@D000A000 {
   compatible = "arm,heliosx-uart";
   reg = <0xd000a000 0x1000="">;
   interrupts = <2>; /* 2, 3 is combined */
  };
...  

===================================================
configuration for compile
===================================================
/arch/arm/configs/heliosx_deconfig
various configuration for compile


===================================================    
UART device driver for boot
  UART output code, 
===================================================          
/arch/arm/include/debug/heliosx.S
  /*
   * addruart_current will check if MMU is enabled and decide
   * which address to use, virtual or physical
   */
  .macro addruart, rp, rv, tmp
  ldr \rp, =UART_PADDR @ physical
  ldr \rv, =UART_VADDR @ virtual
  .endm
...


DT_MACHINE_START(HELIOSX, "HeliosX")
 .map_io  = hx_map_io,
MACHINE_END

===================================================
Add some debug output 
===================================================          
/arch/arm/kernel/atag_parse.c
  early_print
  ...
  
/arch/arm/kernel/setup.c
  setup_arch
  ...
  
===================================================
Add a new machine supporting files
  Kconfig for compile feature select
  Makefile to add heliosx.c 
  Heliosx.c to setup machine
===================================================          
/arch/arm/mach-heliosx/*
static const char * const hx_dt_match[] __initconst = {
 "heliosx",
 NULL,
};

static struct map_desc hx_io_desc[] __initdata = {
 {
  .virtual = (unsigned long) HX_REGS_UART_VIRT_BASE,
  .pfn     = __phys_to_pfn(HX_REGS_UART_PHYS_BASE),
  .length  = HX_REGS_UART_SIZE,
  .type  = MT_DEVICE,

 },
};
...

DT_MACHINE_START(HELIOSX, "HeliosX")
 .map_io  = hx_map_io,
MACHINE_END
...



===================================================
Add debugging info for MMU
===================================================          
/arch/arm/mm/mmu.c


===================================================
Add new machine info 
===================================================          
/arch/arm/tools/mach-types
heliosx   MACH_HELIOSX  HELIOSX
...


===================================================
Add new machine info 
===================================================          
/arch/arm/tools/mach-types


===================================================
Some configuration file
===================================================          
/arch/arm/Kconfig
/arch/arm/Kconfig.debug
/arch/arm/Makefile
config HELIOSX_DRAM_REGION_BASE
 hex "Region base"
 help
   Region base
...

===================================================          
Clock source(timer) driver
  implement functions of clock source framework
  hx_timer_set_next_event, kick of next timer to raise
    interrupt based on "next" timer
===================================================          
/drivers/clocksource/heliosx_timer.c
static void __init hx_timer_init(struct device_node *node)
  setup_irq(irq, &hx_timer_irq)
  ...
  
static irqreturn_t hx_timer_interrupt(int irq, void *dev_id)
  ...  

  
===================================================
Interrupt controller
  handle_one_hxleg, read status register to find out 
    which hardware interrupt is raised.
  calls irq_create_mapping to create HW/SW irq mapping for 16 irq
===================================================          
/drivers/irqchip/irq-heliosx.c
static struct irq_domain_ops hxleg_irqdomain_ops = {
 .map = hxleg_irqdomain_map,
 .xlate = irq_domain_xlate_onetwocell,
};

static void __exception_irq_entry hxleg_handle_irq(struct pt_regs *regs)
{
 int handled;

 do {
  handled = handle_one_hxleg(regs);
 } while (handled);
}

static void __init hxleg_register(struct device_node *node)
{
  ....
  v->domain = irq_domain_add_simple(node, irqsize, 0, &hxleg_irqdomain_ops, v);
  for (i = 0; i < irqsize; i++) {
    irq_create_mapping(v->domain, i);
  }
  ...
}
...

===================================================
UART driver
===================================================   
/drivers/tty/serial/heliosx_uart.c
static void hx_uart_do_rx(struct uart_port *port)
static irqreturn_t hx_uart_interrupt(int irq, void *dev_id)
...

===================================================
HeliosX Port (What is that? I forgot)
===================================================   
/include/uapi/linux/serial_core.h
/* HeliosX Port */
#define PORT_HELIOSX 113
...

Log of A uBoot Hacking Project

/u-boot/arch/arm/lib/board.c
/u-boot/arch/arm/lib/sections.c
  Relocating NAND driver to SPM memory
  Disabling the u-boot's self relocating

/u-boot/board/Marvell/heliosx/heliosx.c
  HeliosX board's hardware init functions

/u-boot/board/Marvell/heliosx/heliosx.lds
  Linker script

/u-boot/common/cmd_tst_*
  Various u-boot command for Helios testing

/u-boot/drivers/mtd/heliosx/*
  HeliosX Nand driver (Not working on simulator)

/u-boot/drivers/serial/serial_heliosx.c
  UART driver

/u-boot/include/configs/heliosx.h
  Configuration setting
  Physical DRAM 128M, start address is (0x08000000)

Log of A Qemu Hacking Project

A Qemu hacking project's log Simulating a proprietary ARM board with its unique interrupt and UART controller.
* Add new configuration
=============================
/default-configs/arm-softmmu.mak
  CONFIG_HELIOSX_UART=y
  CONFIG_HELIOSX_TIMER=y
  CONFIG_HELIOSX_CORE=y
  CONFIG_HELIOSX_VIC=y
  ...


* New board initialization
=============================
/hw/arm/heliosx.c
  hx_init
  ...


* UART device simulation
=============================
/hw/char/heliosx_uart.c
  Simulates the memory mapped registers read/write operation
  static const MemoryRegionOps hx_uart_ops = {
    .read = hx_uart_read,
    .write = hx_uart_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
  };

  hx_uart_rx_interrupt
    qemu_set_irq(s->irq_rx, flags != 0);
  sysbus_init_irq(sbd, &s->irq_rx);
  sysbus_init_irq(sbd, &s->irq_tx);
  ...  


* Add machine initialization parameter  
=============================
/hw/core/machine.c
  Added parameter hxfile1 hxfile2, for loading customized uboot and linux image to machine memory
                     
     
* Interupt controller  
=============================
/hw/intc/heliosx_vic.c
  An legacy, customized interrupt controller. 
  // set up gpio 
  qdev_init_gpio_in(dev, hxvic_set_irq, 16);

  // set up irq, fiq
  sysbus_init_irq(sbd, &s->irq);
  sysbus_init_irq(sbd, &s->fiq);
  ... 
  // invoke cpu interrupt
  qemu_set_irq(s->irq, set);
  
  // called when a gpio signal is asserted
  hxvic_set_irq


* Timer  
=============================
/hw/timer/heliosx_timer.c
  qemu_bh_new(hx_timer_tick, s);
  hx_timer_tick()
    qemu_irq_raise(s->irq);
  ...


* Start up and test script/app
=============================
/hx_test/
  qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin


* Option related
=============================
/util/qemu-config.c
  and customize qemu start option  hxfile1 hxfile2
/vl.c
  option related type
  qemu_ops_set()
  ...


* Build Scripts
=============================
/heliosx_build.sh
/heliosx_config.sh
/heliosx_run.sh
...

Post Code on Blogger

Simplest way to post code to blogger for me: <pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black;overflow-x:...