kernel_ldr: finish implementing all core logic.

This commit is contained in:
Michael Scire
2019-12-17 00:37:55 -08:00
committed by SciresM
parent 623b5f4eb9
commit 8efdd04fcd
20 changed files with 854 additions and 81 deletions

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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 <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern::arm64::cpu {
namespace {
void FlushEntireDataCacheImpl(int level) {
/* Used in multiple locations. */
const u64 level_sel_value = static_cast<u64>(level << 1);
/* Set selection register. */
cpu::SetCsselrEl1(level_sel_value);
cpu::InstructionMemoryBarrier();
/* Get cache size id info. */
CacheSizeIdAccessor ccsidr_el1;
const int num_sets = ccsidr_el1.GetNumberOfSets();
const int num_ways = ccsidr_el1.GetAssociativity();
const int line_size = ccsidr_el1.GetLineSize();
const u64 way_shift = static_cast<u64>(__builtin_clz(num_ways));
const u64 set_shift = static_cast<u64>(line_size + 4);
for (int way = 0; way <= num_ways; way++) {
for (int set = 0; set <= num_sets; set++) {
const u64 way_value = static_cast<u64>(way) << way_shift;
const u64 set_value = static_cast<u64>(set) << set_shift;
const u64 cisw_value = way_value | set_value | level_sel_value;
__asm__ __volatile__("dc cisw, %0" ::"r"(cisw_value) : "memory");
}
}
}
}
void FlushEntireDataCacheShared() {
CacheLineIdAccessor clidr_el1;
const int levels_of_coherency = clidr_el1.GetLevelsOfCoherency();
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
for (int level = levels_of_coherency; level >= levels_of_unification; level--) {
FlushEntireDataCacheImpl(level);
}
}
void FlushEntireDataCacheLocal() {
CacheLineIdAccessor clidr_el1;
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
for (int level = levels_of_unification - 1; level >= 0; level--) {
FlushEntireDataCacheImpl(level);
}
}
}

View File

@@ -39,6 +39,12 @@ namespace ams::kern {
return value;
}
inline u64 GenerateRandomU64() {
u64 value;
smc::GenerateRandomBytes(&value, sizeof(value));
return value;
}
inline smc::MemoryMode GetMemoryMode() {
return static_cast<smc::MemoryMode>((GetKernelConfiguration() >> 10) & 0x3);
}
@@ -73,6 +79,24 @@ namespace ams::kern {
return (GetKernelConfiguration() >> 3) & 1;
}
/* Randomness. */
void KSystemControl::GenerateRandomBytes(void *dst, size_t size) {
MESOSPHERE_ABORT_UNLESS(size <= 0x38);
smc::GenerateRandomBytes(dst, size);
}
u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
/* This is a biased random, but this is okay for now. */
/* TODO: unbiased random? */
const u64 range_size = ((max + 1) - min);
const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
while (true) {
if (const u64 rnd = GenerateRandomU64(); rnd < effective_max) {
return rnd % effective_max;
}
}
}
void KSystemControl::StopSystem() {
/* Display a panic screen via exosphere. */
smc::Panic(0xF00);

View File

@@ -80,6 +80,18 @@ namespace ams::kern::smc {
}
}
void GenerateRandomBytes(void *dst, size_t size) {
/* Call SmcGenerateRandomBytes() */
/* TODO: Lock this to ensure only one core calls at once. */
SecureMonitorArguments args = { FunctionId_GetConfig, size };
MESOSPHERE_ABORT_UNLESS(size <= sizeof(args) - sizeof(args.x[0]));
CallPrivilegedSecureMonitorFunction(args);
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));
/* Copy output. */
std::memcpy(dst, &args.x[1], size);
}
void NORETURN Panic(u32 color) {
SecureMonitorArguments args = { FunctionId_Panic, color };
CallPrivilegedSecureMonitorFunction(args);

View File

@@ -65,6 +65,7 @@ namespace ams::kern::smc {
/* TODO: Rest of Secure Monitor API. */
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
void GenerateRandomBytes(void *dst, size_t size);
void NORETURN Panic(u32 color);
bool ReadWriteRegister(u32 *out, u64 address, u32 mask, u32 value);