blob: 87f54e23e56ec923e98ca3b0dc8c544638c7544f [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* Copyright lowRISC contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/runtime/print.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"
#include "sw/device/lib/testing/test_framework/status.h"
#include "sw/device/lib/testing/test_framework/test_util.h"
#include "sw/device/lib/virtual_memory.h"
OTTF_DEFINE_TEST_CONFIG();
#define CAUSE_USER_ECALL (0x8)
uint32_t supervisor_l1pt[PAGE_SIZE / sizeof(uint32_t)]
__attribute__((aligned(PAGE_SIZE)));
uint32_t supervisor_l2pt[PAGE_SIZE / sizeof(uint32_t)]
__attribute__((aligned(PAGE_SIZE)));
uint32_t user_l2pt[PAGE_SIZE / sizeof(uint32_t)]
__attribute__((aligned(PAGE_SIZE)));
extern uint32_t __VIRTUAL_ROM;
extern uint32_t __virtual_start;
extern uint32_t __virtual_end;
extern uint32_t __SUPER_VIRTUAL_ROM;
extern uint32_t __super_virtual_start;
extern uint32_t __super_virtual_end;
static dif_uart_t smc_uart;
void ottf_store_page_fault_handler(void) { test_status_set(kTestStatusPassed); }
__attribute__((section(".virtual"))) static void umode_fn(void) {
asm volatile(
".option push \n"
".option norvc \n"
"li a1,0xff801000 \n"
"sw zero,0(a1) \n"
"li a4,1 \n"
"fence iorw,ow \n"
"amoadd.w a5,a4,(a1) \n"
"li a1,0 \n"
"amoadd.w a5,a4,(a1) \n"
"fence iorw,ow \n"
".option pop \n");
}
static __attribute__((section(".super_virtual"))) void smode_fn(void) {
user_trampoline((uint32_t)umode_fn);
}
static __attribute__((section(".super_virtual")))
__attribute__((naked, aligned(256))) void
stvec(void) {
asm volatile(
".option push \n"
".option norvc \n"
"ecall \n"
".option pop \n");
}
void _ottf_main(void) {
test_status_set(kTestStatusInTest);
// Initialize the SMC UART to enable logging for non-DV simulation platforms.
if (kDeviceType != kDeviceSimDV) {
init_uart(TOP_MATCHA_SMC_UART_BASE_ADDR, &smc_uart);
}
// Map our code space and UART peripheral.
// Both are mapped such that the virtual addresses
// and physical addresses are the same, but this still
// causes address translation to happen.
machine_map_megapage((void *)TOP_MATCHA_RAM_SMC_BASE_ADDR,
(void *)TOP_MATCHA_RAM_SMC_BASE_ADDR,
(uint32_t *)supervisor_l1pt);
machine_map_megapage((void *)TOP_MATCHA_SMC_UART_BASE_ADDR,
(void *)TOP_MATCHA_SMC_UART_BASE_ADDR,
(uint32_t *)supervisor_l1pt);
// Set up 2-level page tables, one set for user-mode and one set for
// supervisor-mode.
machine_map_region((uint32_t)&__VIRTUAL_ROM, (uint32_t)&__virtual_start,
(uint32_t)&__virtual_end, supervisor_l1pt, user_l2pt,
true);
machine_map_region(
(uint32_t)&__SUPER_VIRTUAL_ROM, (uint32_t)&__super_virtual_start,
(uint32_t)&__super_virtual_end, supervisor_l1pt, supervisor_l2pt, false);
// Calculate the value of the SATP register.
// We enable SV32 virtual memory, and store the page
// containing our page tables.
uint32_t satp = (uint32_t)(0x1llu << 31) | ((uint32_t)supervisor_l1pt >> 12);
// Delegate U-mode ecalls to S-mode.
uint32_t medeleg = (1 << CAUSE_USER_ECALL);
// Execute smode_fn in supervisor mode, after enabling virtual memory.
supervisor_trampoline((uint32_t)smode_fn, (uint32_t)satp, (uint32_t)medeleg,
(uint32_t)stvec, 0 /* mideleg */);
__builtin_unreachable();
}