summaryrefslogtreecommitdiff
path: root/big-little/virtualisor/mem_trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'big-little/virtualisor/mem_trap.c')
-rw-r--r--big-little/virtualisor/mem_trap.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/big-little/virtualisor/mem_trap.c b/big-little/virtualisor/mem_trap.c
new file mode 100644
index 0000000..bd99b52
--- /dev/null
+++ b/big-little/virtualisor/mem_trap.c
@@ -0,0 +1,126 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: mem_trap.c
+ * ----------------------------------------------------------------
+ * $
+ */
+
+#include "virtualisor.h"
+#include "misc.h"
+#include "virt_helpers.h"
+#include "mem_trap.h"
+
+/*
+ * Generic call to make accesses to a peripheral trap into the
+ * HYP mode by invalidating its descriptor in the 2nd stage
+ * translation tables
+ */
+unsigned mem_trap_setup(unsigned periph_addr, mem_trap_data *periph_trap_data)
+{
+ unsigned rc = 0x0, four_kb_index = 0;
+ unsigned one_gb_index = 0, two_mb_index = 0;
+ unsigned long long vtcr = 0x0, hcr = 0x0, level = 0;
+ unsigned long long pagetable_base = 0x0, l2_desc = 0;
+ unsigned long long l3_desc = 0, l3_table = 0;
+
+ /* Check if 2nd stage translations are enabled */
+ hcr = read_hcr();
+ if (!(hcr & HCR_VM)) {
+ printf("%s: 2nd Stage translations not enabled \n", __FUNCTION__);
+ rc = 0x1;
+ goto out;
+ }
+
+ /* Check what level of tables we need to start at */
+ vtcr = read_vtcr();
+ level = (vtcr >> 6) & 0x3;
+
+ /* Read the page table base address. */
+ pagetable_base = read_vttbr();
+
+ /* Calculate the table indices */
+ one_gb_index = periph_addr >> 30;
+
+ /* Each GB contains (1 << 9) or 512 2MBs */
+ two_mb_index = (periph_addr >> 21) - ((1 << 9) * one_gb_index);
+
+ /* Each GB contains (1 << 18) or 262144 4KBs */
+ four_kb_index = (periph_addr >> 12) - ((1 << 9) * (periph_addr >> 21));
+
+ /* For either starting level find out the level 2 desc */
+ switch (level) {
+
+ case 0x1:
+ {
+ /* Start from first level */
+ unsigned long long l1_desc = 0;
+ unsigned long long l2_table = 0;
+
+ l1_desc = ((unsigned long long *)((unsigned)(&pagetable_base)[0]))[one_gb_index];
+ if ((l1_desc & 0x3) != TABLE_MAPPING) {
+ printf("%s: Invalid 1st level desc : 0x%llu \n", __FUNCTION__, l1_desc);
+ rc = 0x1;
+ goto out;
+ }
+
+ l2_table = l1_desc & 0xfffffff000UL;
+ l2_desc = ((unsigned long long *)((unsigned)(&l2_table)[0]))[two_mb_index];
+ break;
+ }
+
+ case 0x0:
+ {
+ /* Start from second level */
+ l2_desc = ((unsigned long long *)((unsigned)(&pagetable_base)[0]))[two_mb_index];
+ break;
+ }
+
+ default:
+ printf("%s: Invalid Pagetable level \n", __FUNCTION__);
+ rc = 0x1;
+ }
+
+ /* Validate the 2nd level descriptor */
+ if ((l2_desc & 0x3) != TABLE_MAPPING) {
+ printf("%s: Invalid 2nd level desc : 0x%llu \n",
+ __FUNCTION__, l2_desc);
+ rc = 0x1;
+ goto out;
+ }
+
+ l3_table = l2_desc & 0xfffffff000UL;
+ l3_desc = ((unsigned long long *)((unsigned)(&l3_table)[0]))[four_kb_index];
+
+ /*
+ * Validate the 3rd level descriptor. This means that the mapping is
+ * already invalid and we have not touched it
+ */
+ if ((l3_desc & 0x3) != VALID_MAPPING) {
+ printf("%s: Invalid 3rd level desc : 0x%llu \n",
+ __FUNCTION__, l3_desc);
+ rc = 0x1;
+ goto out;
+ }
+
+ /* Save the info gathered so far */
+ periph_trap_data->table = l3_table;
+ periph_trap_data->index = four_kb_index;
+ periph_trap_data->prev_desc = l3_desc;
+ periph_trap_data->cluster_id = read_clusterid();
+ periph_trap_data->valid = 1;
+
+ /* Invalidate the peripheral page table entry */
+ ((unsigned long long *)((unsigned)(&l3_table)[0]))[four_kb_index] = 0x0;
+
+ out:
+ return rc;
+}