Skip to content

Instantly share code, notes, and snippets.

@tonosaman
Last active April 27, 2023 14:01
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonosaman/62a31e7991a41edb19c5 to your computer and use it in GitHub Desktop.
Save tonosaman/62a31e7991a41edb19c5 to your computer and use it in GitHub Desktop.
Olimex ARM-USB-OCD-H / openocd-0.9.0 / libftd2xx1.1.12 / Raspberry Pi 2 / Ubuntu 15.04

for RPi2 JTAG debugging with Olimex ARM-USB-OCD-H

System constitution

  • probe device: Olimex ARM-USB-OCD-H
  • target device: Raspberry Pi 2
    • files for booting: bootcode.bin, start.elf, config.txt from here
    • jtag target image armjtag.bin: from here
    • config.txt: edit to add a line kernel=armjtag.bin
  • host machine: Ubuntu 15.04
    • openocd-0.9.0 as debugger host:
      • probe device driver: libftd2xx1.1.12
      • probe device configuration: olimex-arm-usb-ocd-h.cfg (@see below)
      • target device configuration: openocd-rpi2.cfg (@see below)
    • debug client: telnet or gdb
  • pin assign between Olimex ARM-USB-OCD-H and Raspberry Pi 2

Setup FTDI proprietary D2XX driver

This method is obsolete. By openocd warning message, you should use libftdi.

locate libftd2xx.a libftd2xx.so.1.1.12

  • download FTDI proprietary D2XX driver for linux from here
  • installation guide is here
  • extract to ./libftd2xx1.1.12/
  • (optional) locate libraries to /usr/local/lib/
sudo cp libftd2xx1.1.12/build/x86_64/libftd2xx.a /usr/local/lib/
sudo cp libftd2xx1.1.12/build/x86_64/libtd2xx.so.1.1.12 /usr/local/lib/
sudo ln -s /usr/local/lib/libtd2xx.so.1.1.12 /usr/local/lib/libftd2xx.so
sudo chmod 0755 /usr/local/lib/libtd2xx.so.1.1.12

Build OpenOCD

Download "openocd-0.9.0 release" from here

extract to ./openocd-0.9.0

configure options

$ cd openocd-0.9.0
$ ./configure --enable-maintainer-mode --enable-legacy-ft2232_ftd2xx --with-ftd2xx-lib=static --with-ftd2xx-linux-tardir=../libftd2xx1.1.12

Add ld linkage to libpthread

--- src/Makefile.org	2015-07-16 17:51:11.333497970 +0900
+++ src/Makefile	2015-07-16 17:52:06.797236301 +0900
@@ -275,11 +275,11 @@
 INSTALL_SCRIPT = ${INSTALL}
 INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
 LD = /usr/bin/ld -m elf_x86_64
-LDFLAGS =  -L/home/tono/OpenOCD/libftd2xx1.1.12/build/x86_64
+LDFLAGS =  -L/home/tono/OpenOCD/libftd2xx1.1.12/build/x86_64 -L/lib64
 LIBFTDI_CFLAGS = 
 LIBFTDI_LIBS = 
 LIBOBJS = 
-LIBS = -lftd2xx -lrt -ldl 
+LIBS = -lftd2xx -lrt -ldl -lpthread
 LIBTOOL = $(SHELL) $(top_builddir)/libtool
 LIBTOOL_DEPS = ./ltmain.sh
 LIBUSB0_CFLAGS = 

make

$ ldd openocd-0.9.0/src/openocd
	linux-vdso.so.1 =>  (0x00007ffc599bc000)
	libusb-0.1.so.4 => /lib/x86_64-linux-gnu/libusb-0.1.so.4 (0x00007f5dace03000)
	libusb-1.0.so.0 => /lib/x86_64-linux-gnu/libusb-1.0.so.0 (0x00007f5dacbeb000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5dac8e3000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5dac6df000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5dac4c1000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5dac0f7000)
	libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f5dabee4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f5dad00c000)

Paste to olimex-arm-usb-ocd-h.cfg : Configuretion file for openocd 1 of 2

# Olimex ARM-USB-OCD-H
# http://www.olimex.com/dev/arm-usb-ocd-h.html
interface ft2232
ft2232_device_desc "Olimex OpenOCD JTAG ARM-USB-OCD-H"
ft2232_layout olimex-jtag
ft2232_vid_pid 0x15ba 0x002b

Paste to openocd-rpi2.cfg : Configuretion file for openocd 2 of 2

from here Thanks jitomesky! I bought your book!

# ref: http://www.raspberrypi.org/forums/viewtopic.php?f=72&t=100268
#    : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0464f/ch10s06s01.html
 
adapter_khz 1000
adapter_nsrst_delay 400
reset_config none

gdb_breakpoint_override hard

if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME rpi2
}
 
#
# Main DAP
#
if { [info exists DAP_TAPID] } {
   set _DAP_TAPID $DAP_TAPID
} else {
   set _DAP_TAPID 0x4ba00477
}
jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0xf -expected-id $_DAP_TAPID
 
set _TARGETNAME $_CHIPNAME.cpu.0
target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap -coreid 0 -dbgbase 0x80010000
set _TARGETNAME $_CHIPNAME.cpu.1
target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap -coreid 1 -dbgbase 0x80012000
set _TARGETNAME $_CHIPNAME.cpu.2
target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap -coreid 2 -dbgbase 0x80014000
set _TARGETNAME $_CHIPNAME.cpu.3
target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap -coreid 3 -dbgbase 0x80016000
 
$_TARGETNAME configure -event reset-assert-post "cortex_a dbginit"
 
$_TARGETNAME configure -event gdb-attach { halt }

Run openocd

$ rmmod ftdi_sio usbserial
$ sudo src/openocd -f olimex-arm-usb-ocd-h.cfg -f openocd-rpi2.cfg 
[sudo] password for tono: 
Open On-Chip Debugger 0.9.0 (2015-07-16-17:40)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
adapter speed: 1000 kHz
adapter_nsrst_delay: 400
none separate
Warn : Using DEPRECATED interface driver 'ft2232'
Info : Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/...
Info : device: 6 "2232H"
Info : deviceID: 364511275
Info : SerialNumber: OLYPBH2QA
Info : Description: Olimex OpenOCD JTAG ARM-USB-OCD-H A
Info : max TCK change to: 30000 kHz
Info : clock speed 1000 kHz
Info : JTAG tap: rpi2.dap tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : rpi2.cpu.0: hardware has 6 breakpoints, 4 watchpoints
Info : rpi2.cpu.1: hardware has 6 breakpoints, 4 watchpoints
Info : rpi2.cpu.2: hardware has 6 breakpoints, 4 watchpoints
Info : rpi2.cpu.3: hardware has 6 breakpoints, 4 watchpoints

Now connection established, you can see the brinking LED on top of ARM-USB-OCD-H.

connect to openocd server

open another terminal

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt                  
ttbcr 0ttbr0 ca5eaa5attbr1 fd7c7f73
rpi2.cpu.3 rev 5, partnum c07, arch f, variant 0, implementor 41
number of cache level 2
cache l2 present :not supported
rpi2.cpu.3 cluster f core 3 multi core
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x000000c4
MMU: disabled, D-Cache: disabled, I-Cache: disabled

connect to openocd server with using gdb

Download gcc-arm-none-eabi-4_9-2015q1-20150306-linux.tar.bz2 or later from here .

@tonosaman
Copy link
Author

Auto start-up configuration by using GDB script

$ gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/bin/arm-linux-gnueabihf-gdb -x rpi2.gdb xvisor-next/build/vmm.elf

rpi2.gdb

target remote localhost:3333
monitor rpi2.cpu3 arp_halt
monitor rpi2.cpu2 arp_halt
monitor rpi2.cpu1 arp_halt
monitor targets rpi2.cpu0
monitor halt
monitor reset halt
monitor targets
load

@tonosaman
Copy link
Author

Research: Outer Cache prevents JTAG debugging?

References

  • Translation table walk using the Long-descriptor translation table format for stage 1 (p. B3-1510)
  • Stage 2 translation table walk (p. B3-1516)
  • B4.1.74 HTCR, Hyp Trtanslation Control Register, Virtualization Extensions (p. B4-1597)
  • B4.1.159 VTCR, Virtualization Trtanslation Control Register, Virtualization Extensions (p. B4-1738)
  • B3.2.1 VMSA behavior when a stage 1 MMU is disabled (p. B3-1314)
  • B4.1.71 HSCTLR, Hyp System Control Register, Virtualization Extensions (p. B4-1591)

HSCTLR 0x30c50878 -> 0x30c5187d
0x30c50878 ... 0b0011.0000.1100.0101.0000.1000.0111.1000
0x30c5187d ... 0b0011.0000.1100.0101.0001.1000.0111.1101

Bits Name Val Function
[12] I 0b1 Instruction cache enable bit: This is a global enable bit for instruction caches, for memory accesses made in Hyp mode.
[2] C 0b1 Cache enable bit. This is a global enable bit for data and unified caches, for memory accesses made in Hyp mode.
[1] M 0b1 MMU enable bit. This is a global enable bit for the PL2 stage 1 MMU.

Trial Memo

HTCR bits Meaning RPi2 default XVisor set to
ORGN0[11:10] 0b01 Ourter Write-Back Write-Allocate Cacheable Ourter Write-Back Write-Allocate Cacheable Ourter Write-Back Write-Allocate Cacheable
IRGN0[9:8] 0b00 Inner Non-cacheable Inner Non-cacheable Inner Write-Back Write-Alocate Cacheable

set *((int *)__htcr_set) = 0x80803400

VTCR bits Meaning RPi2 default XVisor set to
ORGN0[11:10] 0b00 Ourter Non-cacheable Ourter Non-cacheable Outer Write-Back Write-Allocate Cacheable
IRGN0[9:8] 0b00 Inner Non-cacheable Innver Wirte-Back no Write-Allocate Cacheable Inner Write-Back Write-Alocate Cacheable

set *((int *)__vtcr_set) = 0x80003059

@tonosaman
Copy link
Author

[Solved] Issue: Out of GDB control after enabling MMU with Stage 2 TLB mapping

I have lost GDB debugging control after isb or dsb instruction.

Solution

Add a line gdb_breakpoint_override hard to openocd-rpi2.cfg (config file for openocd).
See detail "Conjecture 3".

Conjecture 1: Some configuration about instruction fetching cause

BUSTED 👎

OpenOCD error message says data about occured.

Error: data abort at 0x696e486c, dfsr = 0x0000004b
Error: data abort at 0xe200001f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b
Error: data abort at 0xf57ff04f, dfsr = 0x0000004b

I guessed this might be caused by using memory mapped debug registers.

  • Table C6-9 v7 Debug memory-mapped and external debug interfaces access behavior (p. C6-2136)

  • Table C6-14 v7.1 Debug memory-mapped and external debug interfaces access behavior

  • OpenOCD access routine @openocd-0.9.0/src/target/cortex_a.c:495

    static int cortex_a_dap_write_memap_register_u32(struct target *target,
    

Conjecture 2: Memory mapped DAP registers can't access from OpenOCD

BUSTED 👎

  • C11.11.21 DBGDSMCR, Debug State MMU Control Register (p. C11-2259)

DAP(0xc0010000, 0xc0012000, 0xc0014000, 0xc0016000) described in openocd-rpi2.cfg are VideoCore's bus-address, not ARM side physical address.

But, JTAG might use peripheral via ARM physical memory range 0x3f000000 to 0x3fffffff(VideoCore map that range to peripheral bus addresses 0x7e000000 to 0x7effffff).

Investigate this hypothesis in next comment.

Info: need appropriate flush TLB while debugging

  • C11.11.21 DBGDSMCR, Debug State MMU Control Register (p. C11-2259)

    If TLB matching is disabled, and TLB maintenance functions have not been correctly performed by the system being debugged, for example, if the TLB has not been flushed following a change to the translation tables, memory accesses made by the debugger might not undergo the same virtual to physical memory mappings as the application being debugged.

    Therefore some debugger disable outer(L2) cache.

Info: What about isb does

In this context, isb means:

> • completed cache, TLB, and branch predictor maintenance operations
  • DDI0406C_C_arm_architecture_reference_manual.pdf (p. A3-153)

    Instruction Synchronization Barrier (ISB)
    An ISB instruction flushes the pipeline in the processor, so that all instructions that come after the ISB instruction in program order are fetched from cache or memory only after the ISB instruction has completed. Using an ISB ensures that the effects of context-changing operations executed before the ISB are visible to the instructions fetched after the ISB instruction. Examples of context-changing operations that require the insertion of an ISB instruction to ensure the effects of the operation are visible to instructions fetched after the ISB instruction are:
    • completed cache, TLB, and branch predictor maintenance operations
    • changes to system control registers.
    Any context-changing operations appearingin program order after the ISB instruction only take effect after the ISB has been executed.

Conjecture 3: gdb step command using rewrite instruction cause broken cache coherency.

From openocd debug log message with -d 3 option.

Debug: 5240 4637036 breakpoints.c:106 breakpoint_add_internal(): added software breakpoint at 0x10000294 of length 0x00000004, (BPID: 21)

Otherwise, according to cortex_a.c it looks like using hardware break point.

static int cortex_a_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
    -> cortex_a_unset_breakpoint()
    stepbreakpoint.type = BKPT_HARD
    -> cortex_a_set_breakpoint(target, &stepbreakpoint, 0x04)

GDB 'step' packet reqired BKPT_SOFT.

Debug: 5504 205298 gdb_server.c:1563 gdb_breakpoint_watchpoint_packet(): -
(gdb) bt
#0  breakpoint_add (target=target@entry=0x86d120, address=address@entry=268436116, length=4, type=type@entry=BKPT_SOFT) at breakpoints.c:226
#1  0x0000000000434414 in gdb_breakpoint_watchpoint_packet (packet=0x7febe0 <gdb_packet_buffer> "Z0,10000294,4", packet_size=<optimized out>, connection=<optimized out>) at gdb_se\
rver.c:1603
#2  gdb_input_inner (connection=<optimized out>) at gdb_server.c:2709
#3  gdb_input (connection=<optimized out>) at gdb_server.c:2876
#4  0x00000000004359fb in server_loop (command_context=0x8193b0) at server.c:473
#5  0x0000000000405563 in openocd_thread (argc=7, argv=0x7fffffffdd98, cmd_ctx=0x8193b0) at openocd.c:301
#6  0x000000000040563e in openocd_main (argc=7, argv=0x7fffffffdd98) at openocd.c:338
#7  0x0000000000404f99 in main (argc=7, argv=0x7fffffffdd98) at main.c:41
(gdb) p type
$15 = BKPT_SOFT
(gdb) p/x address
$17 = 0x10000294

The key for solution is gdb_breakpoint_override_type.
gdb_breakpoint_override_type@openocd-0.9.0/src/server/gdb_server.c#L1583

static int gdb_breakpoint_watchpoint_packet(struct connection *connection, char const *packet, int packet_size)
{
        ...
        if (type == 0)  /* memory breakpoint */
                bp_type = BKPT_SOFT;
        else if (type == 1)     /* hardware breakpoint */
                bp_type = BKPT_HARD;
        ...
        if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT) || (bp_type == BKPT_HARD)))
                bp_type = gdb_breakpoint_override_type;

Add a line to openocd-rpi2.cfg (config file for openocd).

gdb_breakpoint_override hard

Thus, now step working with hardware breakpoint.

Debug: 5148 129070 gdb_server.c:1563 gdb_breakpoint_watchpoint_packet(): -
(gdb) bt
#0  breakpoint_add (target=target@entry=0x86d600, address=address@entry=268436116, length=4, type=type@entry=BKPT_HARD) at breakpoints.c:226
#1  0x0000000000434414 in gdb_breakpoint_watchpoint_packet (packet=0x7febe0 <gdb_packet_buffer> "Z0,10000294,4", packet_size=<optimized out>, connection=<optimized out>) at gdb_se\
rver.c:1603
#2  gdb_input_inner (connection=<optimized out>) at gdb_server.c:2709
#3  gdb_input (connection=<optimized out>) at gdb_server.c:2876
#4  0x00000000004359fb in server_loop (command_context=0x8193b0) at server.c:473
#5  0x0000000000405563 in openocd_thread (argc=7, argv=0x7fffffffdd98, cmd_ctx=0x8193b0) at openocd.c:301
#6  0x000000000040563e in openocd_main (argc=7, argv=0x7fffffffdd98) at openocd.c:338
#7  0x0000000000404f99 in main (argc=7, argv=0x7fffffffdd98) at main.c:41
(gdb) p type
$14 = BKPT_HARD

Conjecture 4:

OpenOCD(=gdbserver) does not recognize that Hypervisor MMU has been enabled.

                LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
                        state[armv7a->armv7a_mmu.mmu_enabled],
                        state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
                        state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);

In this current situation, this matter does not affect the function of step.
Because, we have just set the hypervisor level1 TLB to straight map between virtual address and physical address.

However, by another aspects if we have different mapping between virtual and physical then we should treat properly the status of hypervisor MMU.

static int cortex_a_post_debug_entry(struct target *target)
{
        /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
        retval = armv7a->arm.mrc(target, 15,
                        0, 0,   /* op1, op2 */
                        1, 0,   /* CRn, CRm */
                        &cortex_a->cp15_control_reg);
               armv7a->armv7a_mmu.mmu_enabled =
                        (cortex_a->cp15_control_reg & 0x1U) ? 1 : 0;
        armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled =
                (cortex_a->cp15_control_reg & 0x4U) ? 1 : 0;
        armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled =
                (cortex_a->cp15_control_reg & 0x1000U) ? 1 : 0;
        cortex_a->curr_mode = armv7a->arm.core_mode;


src/target/cortex_a.c:1284:             retval = armv7a->post_debug_entry(target);

@tonosaman
Copy link
Author

Hypervisor MMU settings

  • stage 1 TLB is enabled
    • HSCTLR=0x30c5187d
      • Hypervisor System Control Register
      • (gdb) monitor rpi2.cpu0 arm mrc 15 4 1 0 0
      • M[0] controls Non-secure PL2 stage 1 MMU.
    • HTCR=0x80803500
      • Hypervisor Translation Control Register
      • (gdb) monitor rpi2.cpu0 arm mrc 15 4 2 0 2
    • HTTBR=0x10166000 (=def_ttbl)
      • Hyp Translation Table Base Register, Virtualization Extensions
  • stage 2 TLB is enabled in _reset()@cpu_entry.S
    • HCR=0x00000039

      • Hyp Configuration Register, Virtualization Extensions
      • (gdb) monitor rpi2.cpu0 arm mrc 15 4 1 1 0
      • VM[0] controls Non-secure PL1&0 stage 2 MMU.
      #define HCR_DEFAULT_BITS (HCR_AMO_MASK | HCR_IMO_MASK | HCR_FMO_MASK | HCR_VM_MASK)
    • VTTBR

    • VTCR=0x80003559

      • (gdb) monitor rpi2.cpu0 arm mrc 15 4 2 1 2

Need to map for periferal

This context is under the setting of Non-secure PL2 stage 1 MMU (HTTBR and HTCR) .

MRC p15, 4, <Rt>, c2, c0, 2 ; Read HTCR into Rt
MRRC p15, 4, <Rt>, <Rt2>, c2 ; Read 64-bit HTTBR into Rt (low word) and Rt2 (high word)
chip physical addresses(ARM side address) bus addresses (VideoCore/GPU address) spec.
BCM2836 0x0000_0000 .. 0x3EFF_FFFF 0xC0000000 .. 0xFEFF_FFFF SDRAM (16MB unseen from ARM side)
BCM2836 0x3F00_0000 .. 0x3FFF_FFFF 0x7E000000 .. 0x7EFF_FFFF peripherals @see BCM2835-ARM-Peripherals.pdf
#define BCM2708_PERI_BASE 0x3F000000
#define BCM2708_PAGE_SIZE 0x01000000    /* VC MMU Page Size is 16MB. */
  __setup_initial_ttbl(&lpae_entry, BCM2708_PERI_BASE, BCM2708_PERI_BASE
    + BCM2708_PAGE_SIZE, BCM2708_PERI_BASE, AINDEX_SO, TRUE);
/* 
 * 16MB is same size as Supersection memory block (24-bit offsets).
 * Thus, In Non-secure PL2 stage 1 TLB, Second-level table entries 
 * which associates (8 * 2)MB memory region will be allocated assigned.
 */

@tonosaman
Copy link
Author

Debug arch of RPi2 is v7.1

cpuid = 0x410fc075
ctypr = 0x84448003
ttypr = 0x00000000
didr = 0x3515f005

get_debug_arch()@linux

assert((cpuid >> 16) & 0xf == 0xf);
degug_arch = (didr >> 16) & 0xf;

define ARM_DEBUG_ARCH_V7_1 5

C6.4.1 Using CP14 to access debug registers (p.2123)

  • Register number[9:0]
10 9 8 7 6 5 4 3 2 1 0
0 CRn[3:0] opc2[2:0] Crm[3:0]
MRC p14, 0, <Rt>, <CRn>, <CRm>, <opc2> ; Read
MCR p14, 0, <Rt>, <CRn>, <CRm>, <opc2> ; Write

C6.7 Summary of the v7.1 Debug register interfaces (p.2139)

C11.11.29 DBGLSR, Lock Status Register (p.2267)

  • DBGLSR is only visible in the memory-mapped interface

  • DBGLSR offset = 0xFB4

  • DAP from openocd-rpi2.cfg: rpi2.cpu0 dap debugbase=0xc0010000

  • Thus DBGLSR busaddress is 0xC0010FB4

  • Read DBGLSR

    (gdb) monitor mdw 0xc0010fb4
    0xc0010fb4: 00000000
    

@tonosaman
Copy link
Author

diff --git a/Makefile b/Makefile
index 1098403..44e0faf 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ cppflags+=$(cpu-cppflags)
 cppflags+=$(board-cppflags)
 cppflags+=$(libs-cppflags-y)
 cc=$(CROSS_COMPILE)gcc
-cflags=-g -Wall -nostdlib --sysroot=$(drivers_dir)/include -fno-builtin -D__VMM__
+cflags=-g -O0 -Wall -nostdlib --sysroot=$(drivers_dir)/include -fno-builtin -D__VMM__
 cflags+=$(board-cflags) 
 cflags+=$(cpu-cflags) 
 cflags+=$(libs-cflags-y) 
diff --git a/arch/arm/cpu/common/include/mmu_lpae.h b/arch/arm/cpu/common/include/mmu_lpae.h
index 4b5a73e..adbdf22 100644
--- a/arch/arm/cpu/common/include/mmu_lpae.h
+++ b/arch/arm/cpu/common/include/mmu_lpae.h
@@ -133,6 +133,8 @@ int mmu_lpae_stage2_chttbl(u8 vmid, struct cpu_ttbl *ttbl);
 #define TTBL_L2_INDEX_SHIFT                21
 #define TTBL_L2_BLOCK_SIZE             0x0000000000200000ULL
 #define TTBL_L2_MAP_MASK               (~(TTBL_L2_BLOCK_SIZE - 1))
+#define TTBL_L2_OUTADDR_MASK           0x000000FFFFE00000ULL
+#define TTBL_L2_OUTADDR_SHIFT          21
 /* L3 index Bit[20:12] */
 #define TTBL_L3_INDEX_MASK             0x00000000001FF000ULL
 #define TTBL_L3_INDEX_SHIFT                12
diff --git a/arch/arm/cpu/common/mmu_lpae_entry_ttbl.c b/arch/arm/cpu/common/mmu_lpae_entry_ttbl.c
index d7a231f..366660f 100644
--- a/arch/arm/cpu/common/mmu_lpae_entry_ttbl.c
+++ b/arch/arm/cpu/common/mmu_lpae_entry_ttbl.c
@@ -92,7 +92,25 @@ void __attribute__ ((section(".entry")))
            ttbl =
                (u64 *) (unsigned long)(ttbl[index] &
                            TTBL_OUTADDR_MASK);
-       } else {
+       } else if (page_addr + TTBL_L2_BLOCK_SIZE < map_end) {
+               /* Update level2 block */
+               ttbl[index] =
+                   (((page_addr - map_start) + pa_start) &
+                    TTBL_OUTADDR_MASK);
+               ttbl[index] |= TTBL_STAGE1_LOWER_AF_MASK;
+               ttbl[index] |= (writeable) ?
+                   (TTBL_AP_SRW_U << TTBL_STAGE1_LOWER_AP_SHIFT) :
+                   (TTBL_AP_SR_U << TTBL_STAGE1_LOWER_AP_SHIFT);
+               ttbl[index] |=
+                   (aindex << TTBL_STAGE1_LOWER_AINDEX_SHIFT)
+                   & TTBL_STAGE1_LOWER_AINDEX_MASK;
+               ttbl[index] |= TTBL_STAGE1_LOWER_NS_MASK;
+               ttbl[index] |= (TTBL_SH_INNER_SHAREABLE
+                       << TTBL_STAGE1_LOWER_SH_SHIFT);
+        ttbl[index] |= TTBL_VALID_MASK;
+        page_addr += TTBL_L2_BLOCK_SIZE;
+        continue;
+    } else {
            /* Allocate new level3 table */
            if (lpae_entry->ttbl_count == TTBL_INITIAL_TABLE_COUNT) {
                while (1) ; /* No initial table available */
@@ -244,4 +262,10 @@ void __attribute__ ((section(".entry")))
     */
    __setup_initial_ttbl(&lpae_entry, exec_start, exec_end, load_start,
                 AINDEX_NORMAL_WB, TRUE);
+
+#define BCM2708_PERI_BASE 0x3F000000
+#define BCM2835_PERI_SIZE 0x01000000
+   __setup_initial_ttbl(&lpae_entry, BCM2708_PERI_BASE
+                      , BCM2708_PERI_BASE + BCM2835_PERI_SIZE
+                      , BCM2708_PERI_BASE, AINDEX_SO, TRUE);
 }

@tonosaman
Copy link
Author

@meriororen
Copy link

Hi.

Regarding this line :

umm... openocd-0.9 does not recognize Hypervisor mode of Cortex-A7 MPCore architecture correctly.

How did you solve this? It seems that I keep getting this when I run 'halt' :

Error: invalid mode value encountered 26
Info : ttbcr 0ttbr0 6fb52b5bttbr1 8b10bf69
Info : rp2.cpu.1 rev 5, partnum c07, arch f, variant 0, implementor 41
Info : number of cache level 2
Error: cache l2 present :not supported
Info : rp2.cpu.1 cluster f core 1 multi core
target state: halted
Error: unrecognized psr mode: 0x1a
target halted in ARM state due to debug-request, current mode: UNRECOGNIZED
cpsr: 0x600001da pc: 0x000000cc
MMU: disabled, D-Cache: disabled, I-Cache: disabled

Thank you

@AZO234
Copy link

AZO234 commented Sep 2, 2016

日本語で失礼します。

target halted in ARM state due to debug-request, current mode: Hypervisor

これはOpenOCDにHypervisor用の実装を加えたものでしょうか?
merioromen氏も書いている通り、par mode: 0x1a の解決方法をご教示下さいませ。
(軽い気持ちで src/target/armv4_5.c に実装を加えたらアボートしてしまいました・・・)
Raspberry Pi 3も同様にHYPモード関連でOpenOCDが使い物になりませんね。
SVCモードでもレジスタが触れないのは悲しいです。
更にAArch64・AArch32と、コンパイラやGDBも使い分けなきゃいけないのはしんどいですw

p.s. トノサマン最高です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment