diff --git a/.travis.yml b/.travis.yml index 4b6cc167c..331361c09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,4 +29,4 @@ deploy: secure: Prcon+FjPLo1nh6hdJ1byLAUTMU/vfq3fBLzkxQIyJTVKIeKg9mPVtNoCmvbgxsSVTdS+gPjIoMpt0LgZCUq/cDRJAtOIaAqbm+fVNJBTwgkgwYAG7hCjEprAhUYiqutT+7KhgNZSKUBNJo/w5sWl8xdsSbfHyldGP6XBcocL50= on: tags: true - repo: runtimejs/runtime + repo: runtimejs/runtime \ No newline at end of file diff --git a/README.md b/README.md index bb3a9ccab..e3debd2b2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # runtime.js -[![Build Status](https://travis-ci.org/runtimejs/runtime.svg?branch=master)](https://travis-ci.org/runtimejs/runtime) [![npm](https://img.shields.io/npm/v/runtimejs.svg)](https://www.npmjs.com/package/runtimejs) [![Gem](https://img.shields.io/badge/freenode-%23runtimejs-blue.svg)](https://freenode.net/) [![Travis](https://img.shields.io/badge/GITTER-JOIN_CHAT_%E2%86%92-1dce73.svg)](https://gitter.im/runtimejs/runtime) +[![Build Status](https://travis-ci.org/runtimejs/runtime.svg?branch=master)](https://travis-ci.org/Ross-Computers/runtime) [![npm](https://img.shields.io/npm/v/runtimejs.svg)](https://www.npmjs.com/package/runtimejs) [![Gem](https://img.shields.io/badge/freenode-%23runtimejs-blue.svg)](https://freenode.net/) [![Travis](https://img.shields.io/badge/GITTER-JOIN_CHAT_%E2%86%92-1dce73.svg)](https://gitter.im/runtimejs/runtime) __runtime.js__ is an open-source library operating system (unikernel) for the cloud that runs JavaScript, can be bundled up with an application and deployed as a lightweight and immutable VM image. diff --git a/SConstruct b/SConstruct index 23dc91f43..979bb7b5a 100755 --- a/SConstruct +++ b/SConstruct @@ -2,10 +2,17 @@ import os import sys import datetime +arch = os.getenv('ARCH', "x64") +arch_caps = os.getenv('ARCH', "X64") +bits = os.getenv('BITS', "64") +arch_alt = os.getenv('ALT_ARCH', "x86_64") + SetOption('num_jobs', 4) build = os.getenv('RUNTIME_BUILD', "debug") print 'Build', build +print 'Arch',arch +print 'CPU Bits',bits config = { "project_name": "out/runtimejs", @@ -13,16 +20,16 @@ config = { "toolchain_bin_path": "", "fasm_pathname": "fasm", "link_script": "etc/kernel.ld", - "name_gxx": "x86_64-elf-g++", - "name_gcc": "x86_64-elf-gcc", - "name_as": "x86_64-elf-as", - "name_ld": "x86_64-elf-gcc", - "name_ar": "x86_64-elf-ar", - "name_ranlib": "x86_64-elf-ranlib", - "name_objcopy": "x86_64-elf-objcopy", + "name_gxx": arch_alt+"-elf-g++", + "name_gcc": arch_alt+"-elf-gcc", + "name_as": arch_alt+"-elf-as", + "name_ld": arch_alt+"-elf-gcc", + "name_ar": arch_alt+"-elf-ar", + "name_ranlib": arch_alt+"-elf-ranlib", + "name_objcopy": arch_alt+"-elf-objcopy", "flags_common": { "shared": set([ - '-m64', + '-m'+bits, '-ffreestanding', '-nostdlib', '-mno-red-zone', @@ -38,7 +45,12 @@ config = { '-Wno-unused-parameter', '-fdiagnostics-color', '-D__runtime_js__', - '-DRUNTIMEJS_PLATFORM_X64', + '-DRT_INC_ADDR_SPACE=\', + '-DRT_INC_CPU=\', + '-DRT_INC_IO=\', + '-DRT_INC_IRQ=\', + '-DRT_INC_PLATFORM=\', + '-DRUNTIMEJS_PLATFORM_'+arch_caps, ]), "release": set([ ]), @@ -55,8 +67,8 @@ config = { '-U__STRICT_ANSI__', '-DENABLE_DEBUGGER_SUPPORT', '-DENABLE_DISASSEMBLER', - '-DV8_HOST_ARCH_X64', - '-DV8_TARGET_ARCH_X64', + '-DV8_HOST_ARCH_'+arch_caps, + '-DV8_TARGET_ARCH_'+arch_caps, # '-DV8_DEPRECATION_WARNINGS', # '-DV8_IMMINENT_DEPRECATION_WARNINGS', # '-DVERIFY_HEAP', @@ -85,32 +97,52 @@ config = { }, "flags_link": set([ '-nostdlib', - '-nodefaultlibs', - # '-Map etc/map.txt', + '-nodefaultlibs' ]), "locations": { "cc": [ 'src', 'src/arch', 'src/kernel', - 'src/kernel/x64', + 'src/kernel/arch', + 'src/kernel/arch/'+arch, + 'src/kernel/boot', + 'src/kernel/sys', + 'src/kernel/sys/fs', + 'src/kernel/sys/hw', + 'src/kernel/sys/io', + 'src/kernel/sys/memory', + 'src/kernel/sys/thread', + 'src/kernel/sys/v8', + 'src/kernel/utils', 'src/kernel/profiler', 'src/common', 'test/cc', ], "asm": [ 'src', - 'src/kernel/x64', + 'src/kernel/arch', + 'src/kernel/arch/'+arch, + 'src/kernel/boot', + 'src/kernel/sys', + 'src/kernel/sys/fs', + 'src/kernel/sys/hw', + 'src/kernel/sys/io', + 'src/kernel/sys/memory', + 'src/kernel/sys/thread', + 'src/kernel/sys/v8', + 'src/kernel/utils', + 'src/'+arch ], "js": [ - 'src/kernel/Js', + 'src/kernel/js', ], }, "includes": [ 'deps/musl/src/internal', 'deps/musl/include', - 'deps/musl/arch/x86_64', - 'deps/musl/arch/x86_64/bits', + 'deps/musl/arch/'+arch_alt, + 'deps/musl/arch/'+arch_alt+'/bits', 'deps/libcxx/include', 'deps/v8/include', 'deps/v8', @@ -120,6 +152,8 @@ config = { 'deps/miniz', 'deps/libsodium/src/libsodium/include', 'deps/json11', + 'src/include', + 'src/include/kernel', 'src', 'test', ], @@ -178,6 +212,10 @@ def EnvironmentCreate(build): AR = ar, AS = _as, RANLIB = ranlib, + ARCH = arch, + ARCH_CAPS = arch_caps, + ALT_ARCH = arch_alt, + BITS = bits, CXXFLAGS = " ".join(flags_gxx), CFLAGS = " ".join(flags_gcc), LINK = ld, @@ -186,7 +224,7 @@ def EnvironmentCreate(build): LINKCOMSTR = 'Link $TARGET', RANLIBCOMSTR = 'Index $TARGET', ARCOMSTR = 'Archive $TARGET', - ENV = {'PATH': os.environ['PATH']}, + ENV = {'PATH': os.environ['PATH'],'ARCH': arch,'ARCH_CAPS':arch_caps,'ALT_ARCH':arch_alt,'BITS':bits}, ) env.Append( @@ -216,6 +254,10 @@ def BuildProject(env_base): env.Replace(CPPPATH = config["includes"]) env.Replace(LIBS = config["libs"]) env.Replace(LIBPATH = ['deps']) + env.Replace(ARCH = arch) + env.Replace(ARCH_CAPS = arch_caps) + env.Replace(ALT_ARCH = arch_alt) + env.Replace(BITS = bits) version_header = env.Command('src/kernel/version-autogenerated.h', 'package.json', 'node scripts/update-versions.js') diff --git a/deps/SConscript b/deps/SConscript index c2643a615..6fc158907 100644 --- a/deps/SConscript +++ b/deps/SConscript @@ -1,12 +1,18 @@ +import os Import('env_base') +ARCH = os.getenv('ARCH', "x64") +ARCH_CAPS = os.getenv('ARCH_CAPS', "X64") +ALT_ARCH = os.getenv('ALT_ARCH', "x86_64") +BITS = os.getenv('BITS', "64") + libs_config = { "v8": { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/$ALT_ARCH', + 'musl/arch/$ALT_ARCH/bits', 'libcxx/include', 'eastl/include', 'concurrentqueue', @@ -17,6 +23,8 @@ libs_config = { 'v8/src', 'v8', '../src', + '../src/include', + '../src/include/kernel' ], "source": [ 'v8/src/accessors.cc', @@ -390,30 +398,30 @@ libs_config = { 'v8/src/wasm/wasm-opcodes.cc', 'v8/src/wasm/wasm-result.cc', 'v8/src/zone.cc', - 'v8/src/crankshaft/x64/lithium-codegen-x64.cc', - 'v8/src/crankshaft/x64/lithium-gap-resolver-x64.cc', - 'v8/src/crankshaft/x64/lithium-x64.cc', - 'v8/src/x64/assembler-x64.cc', - 'v8/src/x64/builtins-x64.cc', - 'v8/src/x64/code-stubs-x64.cc', - 'v8/src/x64/codegen-x64.cc', - 'v8/src/x64/cpu-x64.cc', - 'v8/src/x64/deoptimizer-x64.cc', - 'v8/src/x64/disasm-x64.cc', - 'v8/src/x64/frames-x64.cc', - 'v8/src/x64/interface-descriptors-x64.cc', - 'v8/src/x64/macro-assembler-x64.cc', - 'v8/src/debug/x64/debug-x64.cc', - 'v8/src/full-codegen/x64/full-codegen-x64.cc', - 'v8/src/ic/x64/access-compiler-x64.cc', - 'v8/src/ic/x64/handler-compiler-x64.cc', - 'v8/src/ic/x64/ic-x64.cc', - 'v8/src/ic/x64/ic-compiler-x64.cc', - 'v8/src/ic/x64/stub-cache-x64.cc', - 'v8/src/regexp/x64/regexp-macro-assembler-x64.cc', - 'v8/src/compiler/x64/code-generator-x64.cc', - 'v8/src/compiler/x64/instruction-scheduler-x64.cc', - 'v8/src/compiler/x64/instruction-selector-x64.cc', + 'v8/src/crankshaft/'+ARCH+'/lithium-codegen-'+ARCH+'.cc', + 'v8/src/crankshaft/'+ARCH+'/lithium-gap-resolver-'+ARCH+'.cc', + 'v8/src/crankshaft/'+ARCH+'/lithium-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/assembler-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/builtins-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/code-stubs-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/codegen-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/cpu-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/deoptimizer-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/disasm-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/frames-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/interface-descriptors-'+ARCH+'.cc', + 'v8/src/'+ARCH+'/macro-assembler-'+ARCH+'.cc', + 'v8/src/debug/'+ARCH+'/debug-'+ARCH+'.cc', + 'v8/src/full-codegen/'+ARCH+'/full-codegen-'+ARCH+'.cc', + 'v8/src/ic/'+ARCH+'/access-compiler-'+ARCH+'.cc', + 'v8/src/ic/'+ARCH+'/handler-compiler-'+ARCH+'.cc', + 'v8/src/ic/'+ARCH+'/ic-'+ARCH+'.cc', + 'v8/src/ic/'+ARCH+'/ic-compiler-'+ARCH+'.cc', + 'v8/src/ic/'+ARCH+'/stub-cache-'+ARCH+'.cc', + 'v8/src/regexp/'+ARCH+'/regexp-macro-assembler-'+ARCH+'.cc', + 'v8/src/compiler/'+ARCH+'/code-generator-'+ARCH+'.cc', + 'v8/src/compiler/'+ARCH+'/instruction-scheduler-'+ARCH+'.cc', + 'v8/src/compiler/'+ARCH+'/instruction-selector-'+ARCH+'.cc', 'v8/src/base/accounting-allocator.cc', 'v8/src/base/atomicops_internals_x86_gcc.cc', @@ -447,8 +455,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', 'libcxx/include', '../src', ], @@ -472,8 +480,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', 'acpica/source/include', ], "source": [ @@ -1059,8 +1067,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', ], "source": [ 'libcxxrt/src/typeinfo.cc', @@ -1072,8 +1080,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', ], "source": [ 'printf/printf.cc', @@ -1083,8 +1091,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', ], "source": [ 'miniz/tinfl.c', @@ -1094,8 +1102,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', 'libsodium/src/libsodium/include/sodium', ], "source": [ @@ -1243,8 +1251,8 @@ libs_config = { "include": [ 'musl/src/internal', 'musl/include', - 'musl/arch/x86_64', - 'musl/arch/x86_64/bits', + 'musl/arch/'+ALT_ARCH, + 'musl/arch/'+ALT_ARCH+'/bits', 'libcxx/include', 'json11' ], diff --git a/deps/v8/src/base/platform/mutex.h b/deps/v8/src/base/platform/mutex.h index 05e61e7c3..982531738 100644 --- a/deps/v8/src/base/platform/mutex.h +++ b/deps/v8/src/base/platform/mutex.h @@ -16,8 +16,8 @@ #endif #if V8_OS_RUNTIMEJS -#include -#include +#include +#include #endif namespace v8 { diff --git a/etc/kernel.ld b/etc/kernel.ld index 9ccd2df25..bafef559f 100755 --- a/etc/kernel.ld +++ b/etc/kernel.ld @@ -7,7 +7,7 @@ SECTIONS } .text 0x0000000000201000 : { - src/startup.o (.text) + src/kernel/boot/startup.o (.text) *(.text) *(.gnu.linkonce.t*) . = ALIGN(4096); diff --git a/js/__loader.js b/js/__loader.js index 2e9ac3f60..c515a3696 100644 --- a/js/__loader.js +++ b/js/__loader.js @@ -265,6 +265,7 @@ inherits: './modules/inherits.js', sys: 'util/util.js', util: 'util/util.js', + tty: './modules/tty.js', }, runtimePackagePath); loader.require(`${runtimePackagePath}/index.js`); @@ -300,6 +301,8 @@ process.stderr = new StderrStream(); process.termout = new TermoutStream(); process.termerr = new TermerrStream(); + process.argv = process.execArgv = __SYSCALL.getCommandLine().split(" "); + process.title = process.argv0 = process.execPath = process.argv[0]; loader.require('console'); loader.require('/'); })(); diff --git a/js/core/cmos-time.js b/js/core/arch/x64/cmos-time.js similarity index 100% rename from js/core/cmos-time.js rename to js/core/arch/x64/cmos-time.js diff --git a/js/core/pci/index.js b/js/core/arch/x64/pci/index.js similarity index 100% rename from js/core/pci/index.js rename to js/core/arch/x64/pci/index.js diff --git a/js/core/pci/pci-device.js b/js/core/arch/x64/pci/pci-device.js similarity index 100% rename from js/core/pci/pci-device.js rename to js/core/arch/x64/pci/pci-device.js diff --git a/js/core/pci/scan.js b/js/core/arch/x64/pci/scan.js similarity index 100% rename from js/core/pci/scan.js rename to js/core/arch/x64/pci/scan.js diff --git a/js/core/index.js b/js/core/index.js index dcf3f5e31..8fe82f446 100644 --- a/js/core/index.js +++ b/js/core/index.js @@ -21,9 +21,10 @@ const random = require('./random'); const block = require('./block'); const keyboard = require('./keyboard'); const ps2 = require('./ps2'); -const pci = require('./pci'); +const pci = require('./arch/'+process.arch+'/pci'); const net = require('./net'); const stdio = require('./stdio'); +const shell = require('./shell'); class Runtime { constructor() { @@ -36,6 +37,7 @@ class Runtime { allocator, net, stdio, + shell, machine: { reboot: __SYSCALL.reboot, shutdown: () => __SYSCALL.acpiEnterSleepState(5), diff --git a/js/core/shell/index.js b/js/core/shell/index.js new file mode 100644 index 000000000..6e6c5a7ed --- /dev/null +++ b/js/core/shell/index.js @@ -0,0 +1,8 @@ +var shells = new Map(); + +exports.Shell = require("./shell"); +exports.addShell = function(shell) { + if(shells.has(shell.ENV["TERM"])) return false; + shells.set(shell.ENV["TERM"],shell); +}; +exports.shells = shells; \ No newline at end of file diff --git a/js/core/shell/shell.js b/js/core/shell/shell.js new file mode 100644 index 000000000..6199c0db2 --- /dev/null +++ b/js/core/shell/shell.js @@ -0,0 +1,23 @@ +class Shell { + constructor(cmdcb = () => {},promptcb = () => {},name = "rtty",user = "runtime",stdio = runtime.stdio.defaultStdio) { + this.COMMANDS = new Map(); + this.ENV = {}; + this.ENV["TERM"] = name; + this.ENV["USER"] = user; + this.ENV["HOME"] = "/"; + this.ENV["PATH"] = ""; + this.DIR = "/"; + this.HISTORY = []; + this.STDIO = stdio; + this.oncommand = cmdcb; + this.onprompt = promptcb; + }, + run(cmd,argv,cb) { + this.HISTORY.push(cmd+argv.join(" ")); + return this.oncommand(cmd,argv,cb); + }, + prompt(loop) { + return this.onprompt(loop); + } +} +module.exports = Shell; \ No newline at end of file diff --git a/js/core/tty/terminal.js b/js/core/tty/terminal.js index 5e51fb31b..28b364892 100644 --- a/js/core/tty/terminal.js +++ b/js/core/tty/terminal.js @@ -16,11 +16,13 @@ const keyboard = require('../keyboard'); const printer = require('./printer'); const LineEditor = require('./line-editor'); +var terms = []; exports.color = printer.color; exports.print = printer.print; exports.moveOffset = printer.moveOffset; exports.moveTo = printer.moveTo; +exports.terms = terms; let isReading = false; diff --git a/js/driver/ps2/index.js b/js/driver/x64/ps2/index.js similarity index 100% rename from js/driver/ps2/index.js rename to js/driver/x64/ps2/index.js diff --git a/js/driver/ps2/keyboard.js b/js/driver/x64/ps2/keyboard.js similarity index 99% rename from js/driver/ps2/keyboard.js rename to js/driver/x64/ps2/keyboard.js index a8a2b46f9..338a28e6c 100644 --- a/js/driver/ps2/keyboard.js +++ b/js/driver/x64/ps2/keyboard.js @@ -14,7 +14,7 @@ 'use strict'; -const runtime = require('../../core'); +const runtime = require('../../../core'); /* eslint-disable no-multi-spaces, max-len */ const controlKeys = [ diff --git a/js/driver/virtio/blk.js b/js/driver/x64/virtio/blk.js similarity index 98% rename from js/driver/virtio/blk.js rename to js/driver/x64/virtio/blk.js index e11dbe6a0..e666f3dad 100644 --- a/js/driver/virtio/blk.js +++ b/js/driver/x64/virtio/blk.js @@ -14,7 +14,7 @@ 'use strict'; const VirtioDevice = require('./device'); -const runtime = require('../../core'); +const runtime = require('../../../core'); const { Uint64LE } = require('int64-buffer'); const VIRTIO_BLK_T_IN = 0; diff --git a/js/driver/virtio/device.js b/js/driver/x64/virtio/device.js similarity index 100% rename from js/driver/virtio/device.js rename to js/driver/x64/virtio/device.js diff --git a/js/driver/virtio/index.js b/js/driver/x64/virtio/index.js similarity index 97% rename from js/driver/virtio/index.js rename to js/driver/x64/virtio/index.js index df29cf2a1..096adeb2e 100644 --- a/js/driver/virtio/index.js +++ b/js/driver/x64/virtio/index.js @@ -19,7 +19,7 @@ const virtioRNG = require('./rng'); const VIRTIO_SUBSYSTEM_NETWORK = 1; const VIRTIO_SUBSYSTEM_BLOCK = 2; const VIRTIO_SUBSYSTEM_RNG = 4; -const runtime = require('../../core'); +const runtime = require('../../../core'); const driver = { init(pciDevice) { diff --git a/js/driver/virtio/net.js b/js/driver/x64/virtio/net.js similarity index 99% rename from js/driver/virtio/net.js rename to js/driver/x64/virtio/net.js index 8ad600ec7..6235d8c53 100644 --- a/js/driver/virtio/net.js +++ b/js/driver/x64/virtio/net.js @@ -14,7 +14,7 @@ 'use strict'; const VirtioDevice = require('./device'); -const runtime = require('../../core'); +const runtime = require('../../../core'); const { MACAddress, Interface } = runtime.net; const virtioHeader = (() => { diff --git a/js/driver/virtio/rng.js b/js/driver/x64/virtio/rng.js similarity index 97% rename from js/driver/virtio/rng.js rename to js/driver/x64/virtio/rng.js index 1995c2779..533448a2b 100644 --- a/js/driver/virtio/rng.js +++ b/js/driver/x64/virtio/rng.js @@ -14,7 +14,7 @@ 'use strict'; const VirtioDevice = require('./device'); -const runtime = require('../../core'); +const runtime = require('../../../core'); function initializeRNGDevice(pciDevice) { const ioSpace = pciDevice.getBAR(0).resource; diff --git a/js/driver/virtio/vring/available-ring.js b/js/driver/x64/virtio/vring/available-ring.js similarity index 100% rename from js/driver/virtio/vring/available-ring.js rename to js/driver/x64/virtio/vring/available-ring.js diff --git a/js/driver/virtio/vring/descriptor-table.js b/js/driver/x64/virtio/vring/descriptor-table.js similarity index 100% rename from js/driver/virtio/vring/descriptor-table.js rename to js/driver/x64/virtio/vring/descriptor-table.js diff --git a/js/driver/virtio/vring/index.js b/js/driver/x64/virtio/vring/index.js similarity index 98% rename from js/driver/virtio/vring/index.js rename to js/driver/x64/virtio/vring/index.js index b4f0a9728..e7bbfade7 100644 --- a/js/driver/virtio/vring/index.js +++ b/js/driver/x64/virtio/vring/index.js @@ -18,7 +18,7 @@ const assert = require('assert'); const DescriptorTable = require('./descriptor-table'); const AvailableRing = require('./available-ring'); const UsedRing = require('./used-ring'); -const { memoryBarrier } = require('../../../core/atomic'); +const { memoryBarrier } = require('../../../../core/atomic'); const SIZEOF_UINT16 = 2; class VRing { diff --git a/js/driver/virtio/vring/used-ring.js b/js/driver/x64/virtio/vring/used-ring.js similarity index 100% rename from js/driver/virtio/vring/used-ring.js rename to js/driver/x64/virtio/vring/used-ring.js diff --git a/js/index.js b/js/index.js index fd76ddecd..7c2d02793 100644 --- a/js/index.js +++ b/js/index.js @@ -61,11 +61,11 @@ runtime.shell.setCommand('reboot', (args, env, cb) => { // Start device drivers -require('./driver/ps2'); -require('./driver/virtio'); +require('./driver/'+process.arch+'/ps2'); +require('./driver/'+process.arch+'/virtio'); // Set time -require('./core/cmos-time'); // load cmos +require('./core/arch/'+process.arch+'/cmos-time'); // load cmos require('./core/set-time'); // fetch NTP module.exports = runtime; diff --git a/js/modules/os.js b/js/modules/os.js index 83e66de2c..b5e21fe54 100644 --- a/js/modules/os.js +++ b/js/modules/os.js @@ -22,7 +22,7 @@ function mem() { Object.assign(exports, { EOL: '\n', arch: () => process.arch, - cpus: () => [], + cpus: () => Array(__SYSCALL.systemInfo().cpuCount), endianness: () => 'LE', freemem: mem, totalmem: mem, diff --git a/js/modules/process.js b/js/modules/process.js index 536dd062a..25d3e9909 100644 --- a/js/modules/process.js +++ b/js/modules/process.js @@ -30,7 +30,7 @@ class Process extends EventEmitter { abort() { throw new Error('abort()'); }, - arch: 'x64', // since runtime.js only runs in qemu-system-x86_64, it's an x64 system. + arch: __SYSCALL.arch(), // since runtime.js only runs in qemu-system-x86_64, it's an x64 system. argv: [], binding(name) { throw new Error(`no such module: ${name}`); @@ -97,7 +97,9 @@ class Process extends EventEmitter { umask: () => 0, uptime: () => Math.round(performance.now() / 1000), version: '0.0.0', - versions: {}, + versions: { + "v8": __SYSCALL.version()["v8"] + }, }); } } diff --git a/js/modules/tty.js b/js/modules/tty.js new file mode 100644 index 000000000..2618d8279 --- /dev/null +++ b/js/modules/tty.js @@ -0,0 +1,7 @@ +var terms = require("../core/tty/terminal.js").terms; + +function isatty(i) { + return typeof(terms[i]) != "undefined"; +} + +exports.isatty = isatty; \ No newline at end of file diff --git a/package.json b/package.json index d8ee70916..78d7037b0 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,12 @@ }, "repository": { "type": "git", - "url": "git@github.com:runtimejs/runtime.git" + "url": "git@github.com:Ross-Computers/runtime.git" }, "author": "runtime.js project authors", "license": "Apache-2.0", "bugs": { - "url": "https://github.com/runtimejs/runtime/issues" + "url": "https://github.com/Ross-Computers/runtime/issues" }, "homepage": "http://runtimejs.org", "devDependencies": { diff --git a/src/kernel/acpi-manager.h b/src/include/kernel/acpi-manager.h similarity index 100% rename from src/kernel/acpi-manager.h rename to src/include/kernel/acpi-manager.h diff --git a/src/kernel/allocation-tracker.h b/src/include/kernel/allocation-tracker.h similarity index 100% rename from src/kernel/allocation-tracker.h rename to src/include/kernel/allocation-tracker.h diff --git a/src/kernel/boot-services.h b/src/include/kernel/boot-services.h similarity index 100% rename from src/kernel/boot-services.h rename to src/include/kernel/boot-services.h diff --git a/src/kernel/constants.h b/src/include/kernel/constants.h similarity index 100% rename from src/kernel/constants.h rename to src/include/kernel/constants.h diff --git a/src/kernel/cpu.h b/src/include/kernel/cpu.h similarity index 89% rename from src/kernel/cpu.h rename to src/include/kernel/cpu.h index 0a93bb2bb..d05d8f027 100644 --- a/src/kernel/cpu.h +++ b/src/include/kernel/cpu.h @@ -14,11 +14,7 @@ #pragma once -#ifdef RUNTIMEJS_PLATFORM_X64 -#include -#else -#error Platform is not supported -#endif +#include RT_INC_CPU namespace rt { @@ -31,6 +27,14 @@ class Cpu { CpuPlatform::WaitPause(); } + static void Cpuid(int code,uint32_t *a,uint32_t *d) { + CpuPlatform::Cpuid(code,a,d); + } + + static char* Arch() { + return CpuPlatform::Arch(); + } + /** * Disable interrupts and stop execution */ diff --git a/src/kernel/crc32.h b/src/include/kernel/crc32.h similarity index 100% rename from src/kernel/crc32.h rename to src/include/kernel/crc32.h diff --git a/src/kernel/dlmalloc.h b/src/include/kernel/dlmalloc.h similarity index 100% rename from src/kernel/dlmalloc.h rename to src/include/kernel/dlmalloc.h diff --git a/src/kernel/engine.h b/src/include/kernel/engine.h similarity index 100% rename from src/kernel/engine.h rename to src/include/kernel/engine.h diff --git a/src/kernel/engines.h b/src/include/kernel/engines.h similarity index 100% rename from src/kernel/engines.h rename to src/include/kernel/engines.h diff --git a/src/kernel/fileio.h b/src/include/kernel/fileio.h similarity index 100% rename from src/kernel/fileio.h rename to src/include/kernel/fileio.h diff --git a/src/kernel/heap-snapshot.h b/src/include/kernel/heap-snapshot.h similarity index 100% rename from src/kernel/heap-snapshot.h rename to src/include/kernel/heap-snapshot.h diff --git a/src/kernel/initjs.h b/src/include/kernel/initjs.h similarity index 100% rename from src/kernel/initjs.h rename to src/include/kernel/initjs.h diff --git a/src/kernel/initrd.h b/src/include/kernel/initrd.h similarity index 100% rename from src/kernel/initrd.h rename to src/include/kernel/initrd.h diff --git a/src/kernel/irq-dispatcher.h b/src/include/kernel/irq-dispatcher.h similarity index 100% rename from src/kernel/irq-dispatcher.h rename to src/include/kernel/irq-dispatcher.h diff --git a/src/kernel/irqs.h b/src/include/kernel/irqs.h similarity index 88% rename from src/kernel/irqs.h rename to src/include/kernel/irqs.h index 80968d961..71bd0dd0b 100644 --- a/src/kernel/irqs.h +++ b/src/include/kernel/irqs.h @@ -17,11 +17,7 @@ #include #include -#ifdef RUNTIMEJS_PLATFORM_X64 -#include -#else -#error Platform is not supported -#endif +#include RT_INC_IRQ namespace rt { diff --git a/src/kernel/kernel-main.h b/src/include/kernel/kernel-main.h similarity index 100% rename from src/kernel/kernel-main.h rename to src/include/kernel/kernel-main.h diff --git a/src/kernel/kernel.h b/src/include/kernel/kernel.h similarity index 100% rename from src/kernel/kernel.h rename to src/include/kernel/kernel.h diff --git a/src/kernel/keystorage.h b/src/include/kernel/keystorage.h similarity index 100% rename from src/kernel/keystorage.h rename to src/include/kernel/keystorage.h diff --git a/src/kernel/local-storage.h b/src/include/kernel/local-storage.h similarity index 92% rename from src/kernel/local-storage.h rename to src/include/kernel/local-storage.h index 21cdf2d50..c9f00bf72 100644 --- a/src/kernel/local-storage.h +++ b/src/include/kernel/local-storage.h @@ -20,7 +20,7 @@ namespace rt { /** - * Thread local data container. Supports max 16 slots. + * Thread local data container. Supports max 32 slots. */ class LocalStorage { public: @@ -43,7 +43,7 @@ class LocalStorage { DELETE_COPY_AND_ASSIGN(LocalStorage); private: - static const size_t kMaxSlots = 16; + static const size_t kMaxSlots = 32; std::array storage_; uint64_t next_index_; }; diff --git a/src/kernel/logger.h b/src/include/kernel/logger.h similarity index 100% rename from src/kernel/logger.h rename to src/include/kernel/logger.h diff --git a/src/kernel/mem-manager.h b/src/include/kernel/mem-manager.h similarity index 99% rename from src/kernel/mem-manager.h rename to src/include/kernel/mem-manager.h index 10058c6bf..618630f26 100644 --- a/src/kernel/mem-manager.h +++ b/src/include/kernel/mem-manager.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include RT_INC_ADDR_SPACE #include #include #include diff --git a/src/kernel/multiboot.h b/src/include/kernel/multiboot.h similarity index 100% rename from src/kernel/multiboot.h rename to src/include/kernel/multiboot.h diff --git a/src/kernel/native-fn.h b/src/include/kernel/native-fn.h similarity index 100% rename from src/kernel/native-fn.h rename to src/include/kernel/native-fn.h diff --git a/src/kernel/native-object.h b/src/include/kernel/native-object.h similarity index 98% rename from src/kernel/native-object.h rename to src/include/kernel/native-object.h index 3b2308d24..e49ab5d2a 100644 --- a/src/kernel/native-object.h +++ b/src/include/kernel/native-object.h @@ -62,6 +62,8 @@ class NativesObject : public JsObjectWrapper #include -#ifdef RUNTIMEJS_PLATFORM_X64 -#include -#else -#error Platform is not supported -#endif +#include RT_INC_PLATFORM namespace rt { diff --git a/src/kernel/profiler/profiler.h b/src/include/kernel/profiler/profiler.h similarity index 100% rename from src/kernel/profiler/profiler.h rename to src/include/kernel/profiler/profiler.h diff --git a/src/kernel/resource.h b/src/include/kernel/resource.h similarity index 100% rename from src/kernel/resource.h rename to src/include/kernel/resource.h diff --git a/src/kernel/runtime-state.h b/src/include/kernel/runtime-state.h similarity index 100% rename from src/kernel/runtime-state.h rename to src/include/kernel/runtime-state.h diff --git a/src/kernel/spinlock.h b/src/include/kernel/spinlock.h similarity index 100% rename from src/kernel/spinlock.h rename to src/include/kernel/spinlock.h diff --git a/src/kernel/system-context.h b/src/include/kernel/system-context.h similarity index 100% rename from src/kernel/system-context.h rename to src/include/kernel/system-context.h diff --git a/src/kernel/template-cache.h b/src/include/kernel/template-cache.h similarity index 100% rename from src/kernel/template-cache.h rename to src/include/kernel/template-cache.h diff --git a/src/kernel/thread-manager.h b/src/include/kernel/thread-manager.h similarity index 100% rename from src/kernel/thread-manager.h rename to src/include/kernel/thread-manager.h diff --git a/src/kernel/thread.h b/src/include/kernel/thread.h similarity index 100% rename from src/kernel/thread.h rename to src/include/kernel/thread.h diff --git a/src/kernel/threadlib/condvar.h b/src/include/kernel/threadlib/condvar.h similarity index 100% rename from src/kernel/threadlib/condvar.h rename to src/include/kernel/threadlib/condvar.h diff --git a/src/kernel/threadlib/intf.h b/src/include/kernel/threadlib/intf.h similarity index 100% rename from src/kernel/threadlib/intf.h rename to src/include/kernel/threadlib/intf.h diff --git a/src/kernel/threadlib/mutex.h b/src/include/kernel/threadlib/mutex.h similarity index 100% rename from src/kernel/threadlib/mutex.h rename to src/include/kernel/threadlib/mutex.h diff --git a/src/kernel/threadlib/nocopy.h b/src/include/kernel/threadlib/nocopy.h similarity index 100% rename from src/kernel/threadlib/nocopy.h rename to src/include/kernel/threadlib/nocopy.h diff --git a/src/kernel/threadlib/semaphore.h b/src/include/kernel/threadlib/semaphore.h similarity index 100% rename from src/kernel/threadlib/semaphore.h rename to src/include/kernel/threadlib/semaphore.h diff --git a/src/kernel/threadlib/spinlock.h b/src/include/kernel/threadlib/spinlock.h similarity index 100% rename from src/kernel/threadlib/spinlock.h rename to src/include/kernel/threadlib/spinlock.h diff --git a/src/kernel/timeouts.h b/src/include/kernel/timeouts.h similarity index 100% rename from src/kernel/timeouts.h rename to src/include/kernel/timeouts.h diff --git a/src/kernel/trace.h b/src/include/kernel/trace.h similarity index 100% rename from src/kernel/trace.h rename to src/include/kernel/trace.h diff --git a/src/kernel/transport.h b/src/include/kernel/transport.h similarity index 100% rename from src/kernel/transport.h rename to src/include/kernel/transport.h diff --git a/src/kernel/utils.h b/src/include/kernel/utils.h similarity index 100% rename from src/kernel/utils.h rename to src/include/kernel/utils.h diff --git a/src/kernel/v8platform.h b/src/include/kernel/v8platform.h similarity index 100% rename from src/kernel/v8platform.h rename to src/include/kernel/v8platform.h diff --git a/src/kernel/v8utils.h b/src/include/kernel/v8utils.h similarity index 100% rename from src/kernel/v8utils.h rename to src/include/kernel/v8utils.h diff --git a/src/kernel/version.h b/src/include/kernel/version.h similarity index 100% rename from src/kernel/version.h rename to src/include/kernel/version.h diff --git a/src/runtimejs.h b/src/include/runtimejs.h similarity index 100% rename from src/runtimejs.h rename to src/include/runtimejs.h diff --git a/src/kernel/irq-dispatcher.cc b/src/kernel/arch/irq-dispatcher.cc similarity index 96% rename from src/kernel/irq-dispatcher.cc rename to src/kernel/arch/irq-dispatcher.cc index 599511356..892c5d5e9 100644 --- a/src/kernel/irq-dispatcher.cc +++ b/src/kernel/arch/irq-dispatcher.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "irq-dispatcher.h" +#include #include namespace rt { diff --git a/src/kernel/irqs.cc b/src/kernel/arch/irqs.cc similarity index 100% rename from src/kernel/irqs.cc rename to src/kernel/arch/irqs.cc diff --git a/src/kernel/platform.cc b/src/kernel/arch/platform.cc similarity index 100% rename from src/kernel/platform.cc rename to src/kernel/arch/platform.cc diff --git a/src/kernel/x64/acpi-x64.cc b/src/kernel/arch/x64/acpi-x64.cc similarity index 100% rename from src/kernel/x64/acpi-x64.cc rename to src/kernel/arch/x64/acpi-x64.cc diff --git a/src/kernel/x64/acpi-x64.h b/src/kernel/arch/x64/acpi-x64.h similarity index 94% rename from src/kernel/x64/acpi-x64.h rename to src/kernel/arch/x64/acpi-x64.h index e22c21c8c..c95e6f93a 100644 --- a/src/kernel/x64/acpi-x64.h +++ b/src/kernel/arch/x64/acpi-x64.h @@ -18,9 +18,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include namespace rt { diff --git a/src/kernel/x64/address-space-x64.cc b/src/kernel/arch/x64/address-space-x64.cc similarity index 100% rename from src/kernel/x64/address-space-x64.cc rename to src/kernel/arch/x64/address-space-x64.cc diff --git a/src/kernel/x64/address-space-x64.h b/src/kernel/arch/x64/address-space-x64.h similarity index 100% rename from src/kernel/x64/address-space-x64.h rename to src/kernel/arch/x64/address-space-x64.h diff --git a/src/ap_startup.asm b/src/kernel/arch/x64/ap_startup.asm similarity index 100% rename from src/ap_startup.asm rename to src/kernel/arch/x64/ap_startup.asm diff --git a/src/kernel/x64/cpu-trampoline-x64.cc b/src/kernel/arch/x64/cpu-trampoline-x64.cc similarity index 100% rename from src/kernel/x64/cpu-trampoline-x64.cc rename to src/kernel/arch/x64/cpu-trampoline-x64.cc diff --git a/src/kernel/x64/cpu-trampoline-x64.h b/src/kernel/arch/x64/cpu-trampoline-x64.h similarity index 100% rename from src/kernel/x64/cpu-trampoline-x64.h rename to src/kernel/arch/x64/cpu-trampoline-x64.h diff --git a/src/kernel/x64/cpu-x64.cc b/src/kernel/arch/x64/cpu-x64.cc similarity index 95% rename from src/kernel/x64/cpu-x64.cc rename to src/kernel/arch/x64/cpu-x64.cc index 710312f9a..fb4291204 100644 --- a/src/kernel/x64/cpu-x64.cc +++ b/src/kernel/arch/x64/cpu-x64.cc @@ -13,7 +13,7 @@ // limitations under the License. #include "cpu-x64.h" -#include +#include namespace rt { diff --git a/src/kernel/x64/cpu-x64.h b/src/kernel/arch/x64/cpu-x64.h similarity index 92% rename from src/kernel/x64/cpu-x64.h rename to src/kernel/arch/x64/cpu-x64.h index 2c093549b..e00b8bd9c 100644 --- a/src/kernel/x64/cpu-x64.h +++ b/src/kernel/arch/x64/cpu-x64.h @@ -44,6 +44,14 @@ class CpuPlatform { asm volatile("pause" : : : "memory"); } + static void Cpuid(int code, uint32_t *a, uint32_t *d) { + asm volatile("cpuid":"=a"(*a),"=d"(*d):"a"(code):"rcx","rbx"); + } + + static char* Arch() { + return "x64"; + } + /** * Disable interrupts and stop execution */ diff --git a/src/kernel/x64/hpet-x64.cc b/src/kernel/arch/x64/hpet-x64.cc similarity index 100% rename from src/kernel/x64/hpet-x64.cc rename to src/kernel/arch/x64/hpet-x64.cc diff --git a/src/kernel/x64/hpet-x64.h b/src/kernel/arch/x64/hpet-x64.h similarity index 100% rename from src/kernel/x64/hpet-x64.h rename to src/kernel/arch/x64/hpet-x64.h diff --git a/src/kernel/x64/io-x64.h b/src/kernel/arch/x64/io-x64.h similarity index 100% rename from src/kernel/x64/io-x64.h rename to src/kernel/arch/x64/io-x64.h diff --git a/src/kernel/x64/ioapic-x64.cc b/src/kernel/arch/x64/ioapic-x64.cc similarity index 100% rename from src/kernel/x64/ioapic-x64.cc rename to src/kernel/arch/x64/ioapic-x64.cc diff --git a/src/kernel/x64/ioapic-x64.h b/src/kernel/arch/x64/ioapic-x64.h similarity index 100% rename from src/kernel/x64/ioapic-x64.h rename to src/kernel/arch/x64/ioapic-x64.h diff --git a/src/kernel/x64/irq-vectors-x64.asm b/src/kernel/arch/x64/irq-vectors-x64.asm similarity index 100% rename from src/kernel/x64/irq-vectors-x64.asm rename to src/kernel/arch/x64/irq-vectors-x64.asm diff --git a/src/kernel/x64/irqs-x64.cc b/src/kernel/arch/x64/irqs-x64.cc similarity index 99% rename from src/kernel/x64/irqs-x64.cc rename to src/kernel/arch/x64/irqs-x64.cc index 50ebf468e..e222a8fcc 100644 --- a/src/kernel/x64/irqs-x64.cc +++ b/src/kernel/arch/x64/irqs-x64.cc @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include extern "C" { #define GATE(NAME) uint64_t NAME() diff --git a/src/kernel/x64/irqs-x64.h b/src/kernel/arch/x64/irqs-x64.h similarity index 96% rename from src/kernel/x64/irqs-x64.h rename to src/kernel/arch/x64/irqs-x64.h index c71b03c82..b3b4aa8c5 100644 --- a/src/kernel/x64/irqs-x64.h +++ b/src/kernel/arch/x64/irqs-x64.h @@ -14,7 +14,7 @@ #pragma once #include -#include +#include namespace rt { diff --git a/src/kernel/x64/local-apic-x64.cc b/src/kernel/arch/x64/local-apic-x64.cc similarity index 97% rename from src/kernel/x64/local-apic-x64.cc rename to src/kernel/arch/x64/local-apic-x64.cc index 68b40fbb7..6c25a300b 100644 --- a/src/kernel/x64/local-apic-x64.cc +++ b/src/kernel/arch/x64/local-apic-x64.cc @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include namespace rt { diff --git a/src/kernel/x64/local-apic-x64.h b/src/kernel/arch/x64/local-apic-x64.h similarity index 100% rename from src/kernel/x64/local-apic-x64.h rename to src/kernel/arch/x64/local-apic-x64.h diff --git a/src/kernel/x64/platform-x64.cc b/src/kernel/arch/x64/platform-x64.cc similarity index 97% rename from src/kernel/x64/platform-x64.cc rename to src/kernel/arch/x64/platform-x64.cc index 5405e3cd3..185c61242 100644 --- a/src/kernel/x64/platform-x64.cc +++ b/src/kernel/arch/x64/platform-x64.cc @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace rt { diff --git a/src/kernel/x64/platform-x64.h b/src/kernel/arch/x64/platform-x64.h similarity index 93% rename from src/kernel/x64/platform-x64.h rename to src/kernel/arch/x64/platform-x64.h index dae78d43c..d4d10e502 100644 --- a/src/kernel/x64/platform-x64.h +++ b/src/kernel/arch/x64/platform-x64.h @@ -14,8 +14,8 @@ #pragma once #include -#include -#include +#include +#include namespace rt { diff --git a/src/startup.asm b/src/kernel/arch/x64/startup.asm similarity index 100% rename from src/startup.asm rename to src/kernel/arch/x64/startup.asm diff --git a/src/startup_conf.inc b/src/kernel/arch/x64/startup_conf.inc similarity index 100% rename from src/startup_conf.inc rename to src/kernel/arch/x64/startup_conf.inc diff --git a/src/startup_init.inc b/src/kernel/arch/x64/startup_init.inc similarity index 100% rename from src/startup_init.inc rename to src/kernel/arch/x64/startup_init.inc diff --git a/src/kernel/arch/x86/acpi-x86.cc b/src/kernel/arch/x86/acpi-x86.cc new file mode 100644 index 000000000..45e127993 --- /dev/null +++ b/src/kernel/arch/x86/acpi-x86.cc @@ -0,0 +1,274 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "acpi-x86.h" +#include "local-apic-x86.h" +#include + +namespace rt { + +struct AcpiHeader { + uint32_t signature; + uint32_t length; + uint8_t revision; + uint8_t checksum; + uint8_t oem[6]; + uint8_t oemTableId[8]; + uint32_t oemRevision; + uint32_t creatorId; + uint32_t creatorRevision; +} __attribute__((packed)); + +constexpr static uint32_t TableUint32(const char* str) { + return ((uint32_t)str[0] << 0) | + ((uint32_t)str[1] << 8) | + ((uint32_t)str[2] << 16) | + ((uint32_t)str[3] << 24); +} + +static_assert(TableUint32("ABCD") == 0x44434241, + "Invalid table name convertion on current platform."); + +struct AcpiHeaderMADT { + AcpiHeader header; + uint32_t localApicAddr; + uint32_t flags; +} __attribute__((packed)); + +struct AcpiHPETAddress { + uint8_t addressSpaceId; + uint8_t registerBitWidth; + uint8_t registerBitOffset; + uint8_t reserved; + uint64_t address; +} __attribute__((packed)); + +struct AcpiHeaderHPET { + AcpiHeader header; + uint8_t hardwareRevId; + uint8_t comparatorCount : 5; + uint8_t counterSize : 1; + uint8_t reserved : 1; + uint8_t legacyPlacement : 1; + uint16_t pciVendorId; + AcpiHPETAddress address; + uint8_t hpetNumber; + uint16_t minimumTick; + uint8_t pageProtection; +} __attribute__((packed)); + +enum class ApicType : uint8_t { + LOCAL_APIC = 0, + IO_APIC = 1, + INTERRUPT_OVERRIDE = 2 +}; + +struct ApicHeader { + ApicType type; + uint8_t length; +} __attribute__((packed)); + +struct ApicLocalApic { + ApicHeader header; + uint8_t acpiProcessorId; + uint8_t apicId; + uint32_t flags; +} __attribute__((packed)); + +struct ApicIoApic { + ApicHeader header; + uint8_t ioApicId; + uint8_t reserved; + uint32_t ioApicAddress; + uint32_t globalSystemInterrupt; +} __attribute__((packed)); + +void AcpiX86::Init() { + for (uint8_t* p = (uint8_t*)0xe0000; p < (uint8_t*)0x1000000; p += 16) { + uint64_t sig = *(uint64_t*)p; + if (0x2052545020445352 == sig) { // 'RSD PTR ' + if (ParseRSDP(p)) { + break; + } + } + } + + if (io_apics_.size() == 0) { + printf("Unable to find IO APIC to setup interrupts.\n"); + abort(); + } +} + +bool AcpiX86::ParseRSDP(void* p) { + uint8_t* pt = static_cast(p); + + { + uint8_t sum = 0; + for (uint8_t i = 0; i < 20; ++i) { + sum += pt[i]; + } + + if (sum) { + return false; + } + } + + uint8_t rev = pt[15]; + uint32_t rsdt_addr = 0; + + switch (rev) { + case 0: + memcpy(&rsdt_addr, pt + 16, sizeof(uint32_t)); + break; + case 2: + memcpy(&rsdt_addr, pt + 16, sizeof(uint32_t)); + break; + default: + printf("ACPI unknown revision.\n"); + return false; + } + + RT_ASSERT(rsdt_addr); + ParseRSDT(reinterpret_cast((uint64_t)(rsdt_addr))); + return true; +} + +void AcpiX86::ParseRSDT(AcpiHeader* ptr) { + RT_ASSERT(ptr); + + uint32_t* p = reinterpret_cast(ptr + 1); + uint32_t* end = reinterpret_cast((uint8_t*)ptr + ptr->length); + + while (p < end) { + uint64_t addr = static_cast(*p++); + ParseDT((AcpiHeader*)(uintptr_t)addr); + } +} + +void AcpiX86::ParseDT(AcpiHeader* ptr) { + RT_ASSERT(ptr); + uint32_t signature = ptr->signature; + + switch (signature) { + case TableUint32("APIC"): + ParseTableAPIC(reinterpret_cast(ptr)); + break; + case TableUint32("HPET"): + ParseTableHPET(reinterpret_cast(ptr)); + break; + default: + break; + } +} + +void AcpiX86::ParseTableHPET(AcpiHeaderHPET* header) { + RT_ASSERT(header); + if (nullptr != hpet_) { + // Ignore other HPET devices except first one + return; + } + + uint64_t address = header->address.address; + RT_ASSERT(address); + RT_ASSERT(!hpet_); + hpet_ = new HpetX64(reinterpret_cast(address)); + RT_ASSERT(hpet_); +} + +void AcpiX86::ParseTableAPIC(AcpiHeaderMADT* header) { + RT_ASSERT(header); + RT_ASSERT(header->localApicAddr); + + void* local_apic_address = reinterpret_cast( + static_cast(header->localApicAddr)); + + local_apic_address_ = local_apic_address; + local_apic_ = new LocalApicX64(local_apic_address); + + uint8_t* p = (uint8_t*)(header + 1); + uint8_t* end = (uint8_t*)header + header->header.length; + + while (p < end) { + ApicHeader* header = (ApicHeader*)p; + ApicType type = header->type; + uint8_t length = header->length; + + switch (type) { + case ApicType::LOCAL_APIC: { + ApicLocalApic* s = (ApicLocalApic*)p; + AcpiCPU cpu; + cpu.cpu_id = s->acpiProcessorId; + cpu.local_apic_id = s->apicId; + cpu.enabled = (1 == (s->flags & 1)); + cpus_.push_back(cpu); + ++cpu_count_; + } + break; + case ApicType::IO_APIC: { + ApicIoApic* s = (ApicIoApic*)p; + io_apics_.push_back(new IoApicX86(s->ioApicId, + (uintptr_t)s->ioApicAddress, s->globalSystemInterrupt)); + } + break; + case ApicType::INTERRUPT_OVERRIDE: + break; + default: + // TODO: parse others + break; + } + + p += length; + } +} + +void AcpiX86::StartCPUs() { + CpuTrampolineX86 trampoline; + uint8_t startup_vec = 0x08; + + RT_ASSERT(0 == trampoline.cpus_counter_value()); + + uint32_t bsp_apic_id = local_apic_->Id(); + uint16_t cpus_started = 0; + for (const AcpiCPU& cpu : cpus_) { + if (cpu.local_apic_id == bsp_apic_id) { + continue; + } + local_apic_->SendApicInit(cpu.local_apic_id); + } + + GLOBAL_engines()->NonIsolateSleep(50); + + for (const AcpiCPU& cpu : cpus_) { + if (cpu.local_apic_id == bsp_apic_id) { + continue; + } + local_apic_->SendApicStartup(cpu.local_apic_id, startup_vec); + ++cpus_started; + + printf("Starting #%d...\n", cpus_started); + while (trampoline.cpus_counter_value() != cpus_started) { + rt::Cpu::WaitPause(); + } + } + + printf("Cpus: done.\n"); +} + +void AcpiX86::InitIoApics() { + for (IoApicX86* ioa : io_apics_) { + ioa->Init(); + } +} + +} // namespace rt diff --git a/src/kernel/arch/x86/acpi-x86.h b/src/kernel/arch/x86/acpi-x86.h new file mode 100644 index 000000000..d8d67cac4 --- /dev/null +++ b/src/kernel/arch/x86/acpi-x86.h @@ -0,0 +1,90 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace rt { + +struct AcpiHeader; +struct AcpiHeaderMADT; +struct AcpiHeaderHPET; +class LocalApicX86; + +struct AcpiCPU { + uint32_t cpu_id; + uint32_t local_apic_id; + bool enabled; +}; + +class AcpiX86 { +public: + AcpiX86() + : local_apic_(nullptr), + local_apic_address_(nullptr), + hpet_(nullptr), + cpu_count_(0) { + cpus_.reserve(12); + Init(); + RT_ASSERT(local_apic_); + + if (nullptr == hpet_) { + printf("Unable to find HPET device."); + abort(); + } + + RT_ASSERT(hpet_); + } + + LocalApicX86* local_apic() const { + return local_apic_; + } + void* local_apic_address() const { + return local_apic_address_; + } + uint32_t cpus_count() const { + return cpu_count_; + } + + void InitIoApics(); + void StartCPUs(); + + uint64_t BootTimeMicroseconds() const { + return hpet_->ReadMicroseconds(); + } +private: + LocalApicX86* local_apic_; + void* local_apic_address_; + HpetX86* hpet_; + std::vector cpus_; + std::vector io_apics_; + uint32_t cpu_count_; + + void Init(); + bool ParseRSDP(void* p); + void ParseRSDT(AcpiHeader* ptr); + void ParseDT(AcpiHeader* ptr); + void ParseTableAPIC(AcpiHeaderMADT* header); + void ParseTableHPET(AcpiHeaderHPET* header); + DELETE_COPY_AND_ASSIGN(AcpiX86); +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/address-space-x86.cc b/src/kernel/arch/x86/address-space-x86.cc new file mode 100644 index 000000000..22635e250 --- /dev/null +++ b/src/kernel/arch/x86/address-space-x86.cc @@ -0,0 +1,216 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "address-space-x86.h" +#include +#include + +namespace rt { + +AddressSpaceX86::AddressSpaceX86(PageTableAllocator* table_allocator) + : table_allocator_(table_allocator), + pml4_table_(nullptr) { + + RT_ASSERT(table_allocator_); + + // Allocate 1 PML4 table for whole address space + pml4_table_ = table_allocator_->AllocTable(); + RT_ASSERT(pml4_table_); +} + +void AddressSpaceX86::Configure() { + cr3_.IsWriteThrough = false; + cr3_.PageDirectory = pml4_table_; + + uint64_t identity_region = PhysicalAllocator::identity_mapped_region_size(); + RT_ASSERT(identity_region); + + size_t pagesize = PhysicalAllocator::chunk_size(); + RT_ASSERT(pagesize > 0); + size_t pages = identity_region / pagesize; + RT_ASSERT(pages > 0); + + for (size_t i = 0; i < pages; ++i) { + MapPage(reinterpret_cast(pagesize * i), + reinterpret_cast(pagesize * i), false, true); // identity + } +} + +void AddressSpaceX86::Install() { + asm volatile("mov %0, %%cr3":: "b"(cr3_.Encode())); +} + +class VirtualAddressX86 { +public: + explicit VirtualAddressX86(void* address) + : address_(reinterpret_cast(address)) {} + explicit VirtualAddressX86(uintptr_t address) + : address_(address) {} + + inline uint32_t page_offset() const { + uint32_t offset = address_ & 0x1FFFFF; + return offset; + } + + inline uint32_t pd_offset() const { + uint32_t offset = (address_ >> 21) & 0x1FF; + RT_ASSERT(offset < 512); + return offset; + } + + inline uint32_t pdp_offset() const { + uint32_t offset = (address_ >> 30) & 0x1FF; + RT_ASSERT(offset < 512); + return offset; + } + + inline uint32_t pml4_offset() const { + uint32_t offset = (address_ >> 39) & 0x1FF; + RT_ASSERT(offset < 512); + return offset; + } + + inline uintptr_t address() const { + return address_; + } +private: + uintptr_t address_; +}; + +void* AddressSpaceX86::VirtualToPhysical(void* virtaddr) { + VirtualAddressX86 vaddr(virtaddr); + + RT_ASSERT(cr3_.PageDirectory); + PageTable* pml4_table = + reinterpret_cast*>(cr3_.PageDirectory); + RT_ASSERT(pml4_table); + + PML4Entry pml4 = pml4_table->GetEntry(vaddr.pml4_offset()); + if (!pml4.IsPresent) { + return nullptr; + } + + RT_ASSERT(pml4.PageDirectory); + auto pdp_table = reinterpret_cast*>(pml4.PageDirectory); + + PDPEntry pdp = pdp_table->GetEntry(vaddr.pdp_offset()); + if (!pdp.IsPresent) { + return nullptr; + } + + RT_ASSERT(pdp.PageDirectory); + auto pd_table = reinterpret_cast*>(pdp.PageDirectory); + + PDEntry pd = pd_table->GetEntry(vaddr.pd_offset()); + if (!pd.IsPresent) { + return nullptr; + } + + uint8_t* page_addr = reinterpret_cast(pd.PageAddress); + return reinterpret_cast(page_addr + vaddr.page_offset()); +} + +void AddressSpaceX86::MapPage(void* virtaddr, void* physaddr, bool invalidate, bool writethrough) { + VirtualAddressX86 vaddr(virtaddr); + + physaddr = PhysicalAllocator::PageAligned(physaddr); + RT_ASSERT(cr3_.PageDirectory); + PageTable* pml4_table = + reinterpret_cast*>(cr3_.PageDirectory); + RT_ASSERT(pml4_table); + PageTable* pdp_table = nullptr; + PageTable* pd_table = nullptr; + + bool create_pde = false; + bool create_pdpe = false; + bool create_pml4e = false; + + PML4Entry pml4 = pml4_table->GetEntry(vaddr.pml4_offset()); + if (pml4.IsPresent) { + RT_ASSERT(pml4.PageDirectory); + pdp_table = reinterpret_cast*>(pml4.PageDirectory); + + PDPEntry pdp = pdp_table->GetEntry(vaddr.pdp_offset()); + if (pdp.IsPresent) { + RT_ASSERT(pdp.PageDirectory); + pd_table = reinterpret_cast*>(pdp.PageDirectory); + + PDEntry pd = pd_table->GetEntry(vaddr.pd_offset()); + if (pd.IsPresent) { + void* page_addr = pd.PageAddress; + if (physaddr == page_addr) { + return; + } + } else { + create_pde = true; + } + } else { + create_pde = true; + create_pdpe = true; + } + } else { + create_pde = true; + create_pdpe = true; + create_pml4e = true; + } + + if (create_pde) { + PDEntry pd; + pd.IsPresent = true; + pd.IsWriteable = true; + pd.IsWriteThrough = writethrough; + pd.IsPageSize = true; + pd.IsGlobal = false; + pd.PageAddress = physaddr; + + if (nullptr == pd_table) { + pd_table = table_allocator_->AllocTable(); + RT_ASSERT(pd_table); + } + + pd_table->SetEntry(vaddr.pd_offset(), pd); + } + + if (create_pdpe) { + PDPEntry pdp; + pdp.IsPresent = true; + pdp.IsWriteable = true; + pdp.IsWriteThrough = false; + RT_ASSERT(pd_table); + pdp.PageDirectory = pd_table; + + if (nullptr == pdp_table) { + pdp_table = table_allocator_->AllocTable(); + RT_ASSERT(pdp_table); + } + + pdp_table->SetEntry(vaddr.pdp_offset(), pdp); + } + + if (create_pml4e) { + PML4Entry pml4; + pml4.IsPresent = true; + pml4.IsWriteable = true; + pml4.IsWriteThrough = false; + RT_ASSERT(pdp_table); + pml4.PageDirectory = pdp_table; + pml4_table->SetEntry(vaddr.pml4_offset(), pml4); + } + + if (invalidate) { + asm volatile("invlpg (%0)" ::"r" (virtaddr) : "memory"); + } +} + +} // namespace rt diff --git a/src/kernel/arch/x86/address-space-x86.h b/src/kernel/arch/x86/address-space-x86.h new file mode 100644 index 000000000..73cb3c18c --- /dev/null +++ b/src/kernel/arch/x86/address-space-x86.h @@ -0,0 +1,222 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include +#include +#include + +namespace rt { + +class CR3Entry { +public: + bool IsWriteThrough; // PWT + bool IsNotCachable; // PCD + void* PageDirectory; + + CR3Entry() + : IsWriteThrough(false), + IsNotCachable(false), + PageDirectory(nullptr) { } + + explicit CR3Entry(uint64_t entry) + : IsWriteThrough(entry & (1UL << 3)), + IsNotCachable(entry & (1UL << 4)), + PageDirectory(reinterpret_cast(entry & 0xFFFFFFFFFF000)) {} + + uint64_t Encode() const { + RT_ASSERT((reinterpret_cast(PageDirectory) & 0xFFF) == 0); + return ((static_cast(IsWriteThrough) << 3) | + (static_cast(IsNotCachable) << 4) | + (reinterpret_cast(PageDirectory))); + } +}; + +class PML4PDPEntry { +public: + bool IsPresent; // P + bool IsWriteable; // R/W + bool IsUserEnabled; // U/S + bool IsWriteThrough; // PWT + bool IsNotCachable; // PCD + bool IsAccessed; // A + bool IsNoExecute; // NX + void* PageDirectory; + + PML4PDPEntry() + : IsPresent(false), + IsWriteable(false), + IsUserEnabled(false), + IsWriteThrough(false), + IsNotCachable(false), + IsAccessed(false), + IsNoExecute(false), + PageDirectory(nullptr) { } + + explicit PML4PDPEntry(uint64_t entry) + : IsPresent(entry & 1UL), + IsWriteable(entry & (1UL << 1)), + IsUserEnabled(entry & (1UL << 2)), + IsWriteThrough(entry & (1UL << 3)), + IsNotCachable(entry & (1UL << 4)), + IsAccessed(entry & (1UL << 5)), + IsNoExecute(entry & (1UL << 63)), + PageDirectory(reinterpret_cast(entry & 0xFFFFFFFFFF000)) { } + + uint64_t Encode() const { + RT_ASSERT((reinterpret_cast(PageDirectory) & 0xFFF) == 0); + return ((static_cast(IsPresent)) | + (static_cast(IsWriteable) << 1) | + (static_cast(IsUserEnabled) << 2) | + (static_cast(IsWriteThrough) << 3) | + (static_cast(IsNotCachable) << 4) | + (static_cast(IsAccessed) << 5) | + (static_cast(IsNoExecute) << 63) | + (reinterpret_cast(PageDirectory))); + } +}; + +class PML4Entry : public PML4PDPEntry { +public: + PML4Entry() : PML4PDPEntry() { } + explicit PML4Entry(uint64_t entry) : PML4PDPEntry(entry) { } +}; + +class PDPEntry : public PML4PDPEntry { +public: + PDPEntry() : PML4PDPEntry() { } + explicit PDPEntry(uint64_t entry) : PML4PDPEntry(entry) { } +}; + +class PDEntry { +public: + bool IsPresent; // P + bool IsWriteable; // R/W + bool IsUserEnabled; // U/S + bool IsWriteThrough; // PWT + bool IsNotCachable; // PCD + bool IsAccessed; // A + bool IsDirty; // D + bool IsPageSize; // PS, 1 for 2MB + bool IsGlobal; // G + bool IsNoExecute; // NX + void* PageAddress; + + PDEntry() + : IsPresent(false), + IsWriteable(false), + IsUserEnabled(false), + IsWriteThrough(false), + IsNotCachable(false), + IsAccessed(false), + IsDirty(false), + IsPageSize(false), + IsGlobal(false), + IsNoExecute(false), + PageAddress(nullptr) { } + + explicit PDEntry(uint64_t entry) + : IsPresent(entry & 1UL), + IsWriteable(entry & (1UL << 1)), + IsUserEnabled(entry & (1UL << 2)), + IsWriteThrough(entry & (1UL << 3)), + IsNotCachable(entry & (1UL << 4)), + IsAccessed(entry & (1UL << 5)), + IsDirty(entry & (1UL << 6)), + IsPageSize(entry & (1UL << 7)), + IsGlobal(entry & (1UL << 8)), + IsNoExecute(entry & (1UL << 63)), + PageAddress(reinterpret_cast(entry & 0xFFFFFFFE00000)) { } + + uint64_t Encode() const { + RT_ASSERT((reinterpret_cast(PageAddress) & 0x1FFFFF) == 0); + return ((static_cast(IsPresent)) | + (static_cast(IsWriteable) << 1) | + (static_cast(IsUserEnabled) << 2) | + (static_cast(IsWriteThrough) << 3) | + (static_cast(IsNotCachable) << 4) | + (static_cast(IsAccessed) << 5) | + (static_cast(IsDirty) << 6) | + (static_cast(IsPageSize) << 7) | + (static_cast(IsGlobal) << 8) | + (static_cast(IsNoExecute) << 63) | + (reinterpret_cast(PageAddress))); + } +}; + +template +class PageTable { +public: + void* physical_address() { + return reinterpret_cast(this); + } + + void SetEntry(uint32_t index, EntryType entry) { + RT_ASSERT(index < 512); + entries_[index] = entry.Encode(); + } + + EntryType GetEntry(uint32_t index) { + RT_ASSERT(index < 512); + return EntryType(entries_[index]); + } + +protected: + uint64_t entries_[512]; + DELETE_COPY_AND_ASSIGN(PageTable); +}; + +static_assert(sizeof(PageTable) == 4 * 1024, + "Invalid size of PDE, should be 4 KiB."); + +static_assert(sizeof(PageTable) == 4 * 1024, + "Invalid size of PDPE, should be 4 KiB."); + +static_assert(sizeof(PageTable) == 4 * 1024, + "Invalid size of PML4E, should be 4 KiB."); + +class PageTableAllocator; + +class AddressSpaceX86 { +public: + AddressSpaceX86(PageTableAllocator* table_allocator); + + void Install(); + void Configure(); + + /** + * Map virtual address to physical one + */ + void MapPage(void* virtaddr, void* physaddr, bool invalidate, bool writethrough); + + /** + * Convert virtual to physical memory address on this + * address space + */ + void* VirtualToPhysical(void* virtaddr); + + inline static CR3Entry current() { + uint64_t cr3value; + asm volatile("mov %%cr3, %0" : "=r"(cr3value)); + RT_ASSERT(cr3value); + return CR3Entry(cr3value); + } +private: + PageTableAllocator* table_allocator_; + CR3Entry cr3_; + PageTable* pml4_table_; +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/ap_startup.asm b/src/kernel/arch/x86/ap_startup.asm new file mode 100644 index 000000000..96aeca2f6 --- /dev/null +++ b/src/kernel/arch/x86/ap_startup.asm @@ -0,0 +1,100 @@ +; Copyright 2014 runtime.js project authors +; +; 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. + +format ELF64 + +THIS_LOADER_LOCATION = 0x8000 +include 'startup_conf.inc' + +section ".text" align 16 + +public _ap_startup_location +public _ap_startup_start +public _ap_startup_finish +public _cpus_counter + +_ap_startup_location: + +use16 +org THIS_LOADER_LOCATION + +_ap_startup_start: + cli + xor ax,ax + mov ds,ax + mov es,ax + mov ss,ax + mov fs,ax + mov gs,ax + jmp 0x0000:_cs_jump + +_cs_jump: + mov ax, 1 + lock xadd word [_cpus_counter], ax + inc ax + + mov gs, ax + + lgdt [cs:GDTR32] + +; Set protected mode + mov eax, cr0 + or al, 0x01 + mov cr0, eax + + jmp 8:start32 + +align 16 +_cpus_counter: +dq 0 + +use32 + +start32: +; Load data descriptor + mov eax, 16 + +; Write to all segment registers (except GS) + mov ds, ax + mov es, ax + mov ss, ax + xor eax, eax + xor ebx, ebx + xor ecx, ecx + xor edx, edx + xor esi, esi + xor edi, edi + xor ebp, ebp + ;mov esp, 0x8000 + +; Initialize in 32 bit mode + include 'startup_init.inc' + +; Guard + jmp $ + +align 16 +GDTR32: + dw gdt32_end - gdt32 - 1 + dq gdt32 + +align 16 +gdt32: + dw 0x0000, 0x0000, 0x0000, 0x0000 ; NULL + dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; CODE (32 bit) + dw 0xFFFF, 0x0000, 0x9200, 0x00CF ; DATA (32 bit) +gdt32_end: + +_ap_startup_finish: +dd 0 diff --git a/src/kernel/arch/x86/cpu-trampoline-x86.cc b/src/kernel/arch/x86/cpu-trampoline-x86.cc new file mode 100644 index 000000000..a71f91493 --- /dev/null +++ b/src/kernel/arch/x86/cpu-trampoline-x86.cc @@ -0,0 +1,49 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "cpu-trampoline-x86.h" +#include + +// located at 64 bit code location +extern "C" uint8_t _ap_startup_location; + +// located at 16 bit start and finish of code +extern "C" uint8_t _ap_startup_start; +extern "C" uint8_t _ap_startup_finish; + +// other +extern "C" volatile uint16_t _cpus_counter; + +namespace rt { + +CpuTrampolineX86::CpuTrampolineX86() { + RT_ASSERT(reinterpret_cast(&_ap_startup_finish) + > reinterpret_cast(&_ap_startup_start)); + + const void* ap_startup_loc = &_ap_startup_location; + uint16_t ap_startup_len = reinterpret_cast(&_ap_startup_finish) + - reinterpret_cast(&_ap_startup_start); + RT_ASSERT(ap_startup_loc); + RT_ASSERT(ap_startup_len); + + memcpy((void*)kLoadAddress, ap_startup_loc, ap_startup_len); + + printf("AP loader embedded at 0x%x, len = %d\n", ap_startup_loc, ap_startup_len); +} + +uint16_t CpuTrampolineX86::cpus_counter_value() { + return _cpus_counter; +} + +} // namespace rt diff --git a/src/kernel/arch/x86/cpu-trampoline-x86.h b/src/kernel/arch/x86/cpu-trampoline-x86.h new file mode 100644 index 000000000..8dddeae69 --- /dev/null +++ b/src/kernel/arch/x86/cpu-trampoline-x86.h @@ -0,0 +1,33 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include + +namespace rt { + +class CpuTrampolineX86 { +public: + CpuTrampolineX86(); + inline uintptr_t address() { + return kLoadAddress; + } + uint16_t cpus_counter_value(); +private: + const uintptr_t kLoadAddress = 0x8000; + DELETE_COPY_AND_ASSIGN(CpuTrampolineX86); +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/cpu-x86.cc b/src/kernel/arch/x86/cpu-x86.cc new file mode 100644 index 000000000..bd10f26f3 --- /dev/null +++ b/src/kernel/arch/x86/cpu-x86.cc @@ -0,0 +1,22 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "cpu-x86.h" +#include + +namespace rt { + +int SerialPortX86::port_; + +} // namespace rt diff --git a/src/kernel/arch/x86/cpu-x86.h b/src/kernel/arch/x86/cpu-x86.h new file mode 100644 index 000000000..4328d5312 --- /dev/null +++ b/src/kernel/arch/x86/cpu-x86.h @@ -0,0 +1,105 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include + +namespace rt { + +struct CpuMSRValue { + uint32_t lo; + uint32_t hi; + CpuMSRValue() : lo(0), hi(0) { } + CpuMSRValue(uint32_t lo_, uint32_t hi_) : lo(lo_), hi(hi_) { } +}; + +class CpuPlatform { +public: + static CpuMSRValue GetMSR(uint32_t msr) { + CpuMSRValue value; + asm volatile("rdmsr" : "=a"(value.lo), "=d"(value.hi) : "c"(msr)); + return value; + } + + static void SetMSR(uint32_t msr, CpuMSRValue value) { + asm volatile("wrmsr" : : "a"(value.lo), "d"(value.hi), "c"(msr)); + } + + /** + * Pause operation for busy-wait loops + */ + static void WaitPause() { + asm volatile("pause" : : : "memory"); + } + + static void Cpuid(int code, uint32_t *a, uint32_t *d) { + asm volatile("cpuid":"=a"(*a),"=d"(*d):"a"(code):"ecx","ebx"); + } + + static char* Arch() { + return "x86"; + } + + /** + * Disable interrupts and stop execution + */ + __attribute__((__noreturn__)) static void HangSystem() { + asm volatile ("cli"); + for (;;) { + WaitPause(); + } + } + + /** + * Get current CPU index + */ + static uint32_t id() { + uint16_t gs = 0; // gs contains cpu id + asm volatile("movw %%gs,%0" : "=r"(gs)); + return gs; + } + + /** + * Clear IF flag so the interrupt can not occur + */ + inline static void DisableInterrupts() { + asm volatile("cli"); + } + + /** + * Set IF flag to be able to receive interrupts + */ + inline static void EnableInterrupts() { + asm volatile("sti"); + } + + /** + * Get interrupts enabled status + */ + inline static bool IsInterruptsEnabled() { + uint32_t eflags; + asm volatile("pushf; pop %0" : "=r" (eflags)); + return 1 == (eflags & 0x200); + } + + /** + * Put current CPU into sleep until next interrupt + */ + inline static void Halt() { + asm volatile("hlt"); + } +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/hpet-x86.cc b/src/kernel/arch/x86/hpet-x86.cc new file mode 100644 index 000000000..30e7d4b08 --- /dev/null +++ b/src/kernel/arch/x86/hpet-x86.cc @@ -0,0 +1,68 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "hpet-x86.h" +#include +#include + +namespace rt { + +HpetX86::HpetX86(void* address) + : address_(address), + registers_(reinterpret_cast(address)), + counter_(reinterpret_cast( + reinterpret_cast(address) + kCounterOffset)), + frequency_(0), + us_div_(0) { + RT_ASSERT(registers_); + + uint32_t period = registers_->counterPeriod; // in femptoseconds (10^-15 seconds) + + // TODO: don't use HPET if this fails + RT_ASSERT(0 != period); + RT_ASSERT(period <= 0x05F5E100); + + if (!registers_->generalCapabilities & kCapabilitiesCounterSizeMask) { + printf("[HPET] 32 bit counter (!)\n"); + } + + frequency_ = /* 10^15 */ 1000000000000000 / period; + + // TODO: don't use HPET if this fails + RT_ASSERT(frequency_ >= 1000000); + us_div_ = frequency_ / 1000000; + RT_ASSERT(us_div_ > 0); + +#if 0 + // Setup periodic profiler timer + uint64_t interval = (100 * us_div_); /* 100 microseconds */ + + auto timer_config = GetTimerConfig(0); + uint32_t irq_bits = timer_config->config >> 32; + uint32_t irq_number = __builtin_ctz(irq_bits); + + RT_ASSERT(0x10 == (timer_config->config & 0x10) && "HPET No periodic support"); + +// timer_config->config = (irq_number << 9) | (1 << 2) | (1 << 3) | (1 << 6); +// timer_config->comparatorValue = interval; +// timer_config->comparatorValue = interval; +#endif + + ResetCounter(); + Cpu::WaitPause(); + registers_->generalConfiguration |= kConfigurationEnable; + Cpu::WaitPause(); +} + +} // namespace rt diff --git a/src/kernel/arch/x86/hpet-x86.h b/src/kernel/arch/x86/hpet-x86.h new file mode 100644 index 000000000..cd20d0a69 --- /dev/null +++ b/src/kernel/arch/x86/hpet-x86.h @@ -0,0 +1,81 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include + +namespace rt { + +struct HPETRegisters { + uint32_t generalCapabilities; + uint32_t counterPeriod; + uint64_t reserved0; + uint64_t generalConfiguration; + uint64_t reserved1; + uint64_t generalInterruptStatus; +} __attribute__((packed)); + +struct HPETTimerConfig { + uint64_t config; + uint64_t comparatorValue; + uint64_t interruptRoute; + uint64_t reserved0; +}; + +class HpetX86 { +public: + /** + * Create HPET instance using registers base address + */ + HpetX86(void* address); + + /** + * Read counter value converted to microseconds + */ + uint64_t ReadMicroseconds() const { + return ReadCounter() / us_div_; + } + + /** + * Read raw counter value + */ + uint64_t ReadCounter() const { + return *counter_; + } + + /** + * Reset counter (must be disabled) + */ + void ResetCounter() { + *counter_ = 0; + } + + HPETTimerConfig* GetTimerConfig(uint8_t timer_index) { + return reinterpret_cast(reinterpret_cast(address_) + + kTimerConfigsOffset + sizeof(HPETTimerConfig) * timer_index); + } +private: + static const int kCapabilitiesCounterSizeMask = (1 << 13); + static const int kConfigurationEnable = (1 << 0); + static const int kCounterOffset = 0x0f0; + static const int kTimerConfigsOffset = 0x100; + void* address_; + HPETRegisters* registers_; + volatile uint64_t* counter_; + uint64_t frequency_; + uint64_t us_div_; +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/io-x86.h b/src/kernel/arch/x86/io-x86.h new file mode 100644 index 000000000..82d08ecaf --- /dev/null +++ b/src/kernel/arch/x86/io-x86.h @@ -0,0 +1,133 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once +#include + +namespace rt { + +/** + * Functions to read and write IO ports + */ +class IoPortsX86 { +public: + inline static void OutB(uint16_t port, uint8_t value) { + asm volatile("outb %b0,%w1":: "a"(value), "d"(port)); + } + + inline static void OutW(uint16_t port, uint16_t value) { + asm volatile("outw %w0,%w1":: "a"(value), "d"(port)); + } + + inline static void OutDW(uint16_t port, uint32_t value) { + asm volatile("outl %0,%w1":: "a"(value), "Nd"(port)); + } + + inline static uint8_t InB(uint16_t port) { + uint8_t value; + asm volatile("inb %w1, %b0": "=a"(value): "d"(port)); + return value; + } + + inline static uint16_t InW(uint16_t port) { + uint16_t value; + asm volatile("inw %w1, %w0": "=a"(value): "d"(port)); + return value; + } + + inline static uint32_t InDW(uint16_t port) { + uint32_t value; + asm volatile("inl %w1, %0": "=a"(value): "Nd"(port)); + return value; + } + + inline static uint8_t PciReadB(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + PciWriteAddr(bus, slot, func, offset); + return (uint8_t)((InDW(kPciDataPort) >> ((offset & 3) * 8)) & 0xff); + } + + inline static uint16_t PciReadW(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + RT_ASSERT((offset & 1) == 0); // aligned check + PciWriteAddr(bus, slot, func, offset); + return (uint16_t)((InDW(kPciDataPort) >> ((offset & 2) * 8)) & 0xffff); + } + + inline static uint32_t PciReadDW(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + RT_ASSERT((offset & 3) == 0); // aligned check + PciWriteAddr(bus, slot, func, offset); + return (uint32_t)InDW(kPciDataPort); + } + + inline static void PciWriteB(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint8_t value) { + PciWriteAddr(bus, slot, func, offset); + OutB(kPciDataPort + (offset & 3), value); + } + + inline static void PciWriteW(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint16_t value) { + RT_ASSERT((offset & 1) == 0); // aligned check + PciWriteAddr(bus, slot, func, offset); + OutW(kPciDataPort + (offset & 2), value); + } + + inline static void PciWriteDW(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t value) { + RT_ASSERT((offset & 3) == 0); // aligned check + PciWriteAddr(bus, slot, func, offset); + OutDW(kPciDataPort, value); + } +private: + static const uint32_t kPciAddressPort = 0xCF8; + static const uint32_t kPciDataPort = 0xCFC; + + static void PciWriteAddr(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + RT_ASSERT(slot < 32); + RT_ASSERT(func < 8); + uint32_t addr = (uint32_t)(((uint32_t)bus << 16) | ((uint32_t)slot << 11) | + ((uint32_t)func << 8) | (offset & 0xfc) | ((uint32_t)0x80000000)); + OutDW(kPciAddressPort, addr); + } +}; + +/** + * Serial port output + */ +class SerialPortX86 { +public: + inline static void Init() { + port_ = 0x3F8; // COM1 + IoPortsX86::OutB(port_ + 1, 0x00); // Disable all interrupts + IoPortsX86::OutB(port_ + 3, 0x80); // Enable DLAB (set baud rate divisor) + IoPortsX86::OutB(port_ + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + IoPortsX86::OutB(port_ + 1, 0x00); // (hi byte) + IoPortsX86::OutB(port_ + 3, 0x03); // 8 bits, no parity, one stop bit + IoPortsX86::OutB(port_ + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + IoPortsX86::OutB(port_ + 4, 0x0B); // IRQs enabled, RTS/DSR set + } + + inline static void WriteByte(char a) { + write_serial(a); + } + + inline static int is_transmit_empty() { + return IoPortsX86::InB(port_ + 5) & 0x20; + } + + inline static void write_serial(char a) { + while (is_transmit_empty() == 0); + IoPortsX86::OutB(port_, a); + } +private: + static int port_; +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/ioapic-x86.cc b/src/kernel/arch/x86/ioapic-x86.cc new file mode 100644 index 000000000..8e572c82c --- /dev/null +++ b/src/kernel/arch/x86/ioapic-x86.cc @@ -0,0 +1,59 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "ioapic-x86.h" +#include + +namespace rt { + +IoApicX86::IoApicX86(uint32_t id, uintptr_t address, uint32_t interrupt_base) + : id_(id), + address_(address), + interrupt_base_(interrupt_base), + registers_(IoApicRegistersAccessor(address)) {} + +void IoApicX86::Init() { + RT_ASSERT(address_); + uint32_t id_reg = (registers_.Read(IoApicRegister::ID) >> 24) & 0xF; + + if (id_reg != id_) { + registers_.Write(IoApicRegister::ID, 0, id_ << 24); + printf("Patch APICID = %d, was = %d\n", id_, id_reg); + } + +// RT_ASSERT(id_reg == id_); + uint32_t max_value = (registers_.Read(IoApicRegister::VER) >> 16) & 0xFF; + RT_ASSERT(max_value); + + uint32_t max_interrupts = max_value + 1; + + const uint32_t kIntMasked = 1 << 16; + const uint32_t kIntTrigger = 1 << 15; + const uint32_t kIntActiveLow = 1 << 14; + const uint32_t kIntDstLogical = 1 << 11; + const uint32_t kIRQOffset = 32; + + // Enable all interrupts + for (uint32_t i = 0; i < max_interrupts; ++i) { + // Mask timer (timer doesn't go through IOAPIC) + if (0 == interrupt_base_ && (0 == i)) { + registers_.SetEntry(i, kIntMasked | (kIRQOffset + i)); + continue; + } + + EnableIrq(kIRQOffset, i); + } +} + +} // namespace rt diff --git a/src/kernel/arch/x86/ioapic-x86.h b/src/kernel/arch/x86/ioapic-x86.h new file mode 100644 index 000000000..b753044e7 --- /dev/null +++ b/src/kernel/arch/x86/ioapic-x86.h @@ -0,0 +1,87 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include +#include + +namespace rt { + +enum class IoApicAccessorRegister { + IOREGSEL = 0x00, // Register selector + IOWIN = 0x10 // Register data +}; + +enum class IoApicRegister { + ID = 0x00, // IO APIC ID + VER = 0x01, // IO APIC Version / Max Redirection Entry + ARB = 0x02, // APIC Arbitration ID + REDTBL = 0x10 // Redirection Entries +}; + +class IoApicRegistersAccessor { +public: + explicit IoApicRegistersAccessor(uintptr_t address) + : address_(address) { + RT_ASSERT(address); + } + + inline uint32_t Read(IoApicRegister reg) const { + RT_ASSERT(address_); + *(volatile uint32_t*)(address_ + + static_cast(IoApicAccessorRegister::IOREGSEL)) + = static_cast(reg); + + return *(volatile uint32_t*)(address_ + + static_cast(IoApicAccessorRegister::IOWIN)); + } + + inline void Write(IoApicRegister reg, uint8_t reg_offset, uint32_t value) const { + RT_ASSERT(address_); + *(volatile uint32_t*)(address_ + + static_cast(IoApicAccessorRegister::IOREGSEL)) + = static_cast(reg) + reg_offset; + + *(volatile uint32_t*)(address_ + + static_cast(IoApicAccessorRegister::IOWIN)) = value; + } + + inline void SetEntry(uint8_t index, uint64_t data) const { + Write(IoApicRegister::REDTBL, index * 2, static_cast(data)); + Write(IoApicRegister::REDTBL, index * 2 + 1, static_cast(data >> 32)); + } +private: + uintptr_t address_; +}; + +class IoApicX86 { +public: + IoApicX86(uint32_t id, uintptr_t address, uint32_t interrupt_base); + + void Init(); + + void EnableIrq(uint32_t first_irq_offset, uint32_t irq) { + registers_.SetEntry(irq, first_irq_offset + irq + interrupt_base_); + } + +private: + uint32_t id_; + uintptr_t address_; + uint32_t interrupt_base_; + IoApicRegistersAccessor registers_; + DELETE_COPY_AND_ASSIGN(IoApicX86); +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/irq-vectors-x86.asm b/src/kernel/arch/x86/irq-vectors-x86.asm new file mode 100644 index 000000000..09cdad11a --- /dev/null +++ b/src/kernel/arch/x86/irq-vectors-x86.asm @@ -0,0 +1,843 @@ +; Copyright 2014 runtime.js project authors +; +; Licensed under the Apache License, Veesion 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. + +format ELF64 + +section ".text" align 16 +use64 + +public _preemptStart as 'preemptStart' +public _threadStructInit as 'threadStructInit' +public _enterFirstThread as 'enterFirstThread' + +public _int_gate_exception_DE as 'int_gate_exception_DE' +public _int_gate_exception_DB as 'int_gate_exception_DB' +public _int_gate_exception_NMI as 'int_gate_exception_NMI' +public _int_gate_exception_BP as 'int_gate_exception_BP' +public _int_gate_exception_OF as 'int_gate_exception_OF' +public _int_gate_exception_BR as 'int_gate_exception_BR' +public _int_gate_exception_UD as 'int_gate_exception_UD' +public _int_gate_exception_NM as 'int_gate_exception_NM' +public _int_gate_exception_DF as 'int_gate_exception_DF' +public _int_gate_exception_TS as 'int_gate_exception_TS' +public _int_gate_exception_NP as 'int_gate_exception_NP' +public _int_gate_exception_SS as 'int_gate_exception_SS' +public _int_gate_exception_GP as 'int_gate_exception_GP' +public _int_gate_exception_PF as 'int_gate_exception_PF' +public _int_gate_exception_MF as 'int_gate_exception_MF' +public _int_gate_exception_AC as 'int_gate_exception_AC' +public _int_gate_exception_MC as 'int_gate_exception_MC' +public _int_gate_exception_XF as 'int_gate_exception_XF' +public _int_gate_exception_SX as 'int_gate_exception_SX' +public _int_gate_exception_other as 'int_gate_exception_other' + +public _int_gate_irq_timer as 'int_gate_irq_timer' +public _int_gate_irq_keyboard as 'int_gate_irq_keyboard' +public _int_gate_irq_spurious as 'int_gate_irq_spurious' + +public _switch_to_stack as 'switch_to_stack' + +public _irq_gate_20 +public _irq_gate_21 +public _irq_gate_22 +public _irq_gate_23 +public _irq_gate_24 +public _irq_gate_25 +public _irq_gate_26 +public _irq_gate_27 +public _irq_gate_28 +public _irq_gate_29 +public _irq_gate_2a +public _irq_gate_2b +public _irq_gate_2c +public _irq_gate_2d +public _irq_gate_2e +public _irq_gate_2f +public _irq_gate_30 +public _irq_gate_31 +public _irq_gate_32 +public _irq_gate_33 +public _irq_gate_34 +public _irq_gate_35 +public _irq_gate_36 +public _irq_gate_37 +public _irq_gate_38 +public _irq_gate_39 +public _irq_gate_3a +public _irq_gate_3b +public _irq_gate_3c +public _irq_gate_3d +public _irq_gate_3e +public _irq_gate_3f +public _irq_gate_40 +public _irq_gate_41 +public _irq_gate_42 +public _irq_gate_43 +public _irq_gate_44 +public _irq_gate_45 +public _irq_gate_46 +public _irq_gate_47 +public _irq_gate_48 +public _irq_gate_49 +public _irq_gate_4a +public _irq_gate_4b +public _irq_gate_4c +public _irq_gate_4d +public _irq_gate_4e +public _irq_gate_4f +public _irq_gate_50 +public _irq_gate_51 +public _irq_gate_52 +public _irq_gate_53 +public _irq_gate_54 +public _irq_gate_55 +public _irq_gate_56 +public _irq_gate_57 +public _irq_gate_58 +public _irq_gate_59 +public _irq_gate_5a +public _irq_gate_5b +public _irq_gate_5c +public _irq_gate_5d +public _irq_gate_5e +public _irq_gate_5f +public _irq_gate_60 +public _irq_gate_61 +public _irq_gate_62 +public _irq_gate_63 +public _irq_gate_64 +public _irq_gate_65 +public _irq_gate_66 +public _irq_gate_67 +public _irq_gate_68 +public _irq_gate_69 +public _irq_gate_6a +public _irq_gate_6b +public _irq_gate_6c +public _irq_gate_6d +public _irq_gate_6e +public _irq_gate_6f +public _irq_gate_70 +public _irq_gate_71 +public _irq_gate_72 +public _irq_gate_73 +public _irq_gate_74 +public _irq_gate_75 +public _irq_gate_76 +public _irq_gate_77 +public _irq_gate_78 +public _irq_gate_79 +public _irq_gate_7a +public _irq_gate_7b +public _irq_gate_7c +public _irq_gate_7d +public _irq_gate_7e +public _irq_gate_7f +public _irq_gate_80 +public _irq_gate_81 +public _irq_gate_82 +public _irq_gate_83 +public _irq_gate_84 +public _irq_gate_85 +public _irq_gate_86 +public _irq_gate_87 +public _irq_gate_88 +public _irq_gate_89 +public _irq_gate_8a +public _irq_gate_8b +public _irq_gate_8c +public _irq_gate_8d +public _irq_gate_8e +public _irq_gate_8f +public _irq_gate_90 +public _irq_gate_91 +public _irq_gate_92 +public _irq_gate_93 +public _irq_gate_94 +public _irq_gate_95 +public _irq_gate_96 +public _irq_gate_97 +public _irq_gate_98 +public _irq_gate_99 +public _irq_gate_9a +public _irq_gate_9b +public _irq_gate_9c +public _irq_gate_9d +public _irq_gate_9e +public _irq_gate_9f +public _irq_gate_a0 +public _irq_gate_a1 +public _irq_gate_a2 +public _irq_gate_a3 +public _irq_gate_a4 +public _irq_gate_a5 +public _irq_gate_a6 +public _irq_gate_a7 +public _irq_gate_a8 +public _irq_gate_a9 +public _irq_gate_aa +public _irq_gate_ab +public _irq_gate_ac +public _irq_gate_ad +public _irq_gate_ae +public _irq_gate_af +public _irq_gate_b0 +public _irq_gate_b1 +public _irq_gate_b2 +public _irq_gate_b3 +public _irq_gate_b4 +public _irq_gate_b5 +public _irq_gate_b6 +public _irq_gate_b7 +public _irq_gate_b8 +public _irq_gate_b9 +public _irq_gate_ba +public _irq_gate_bb +public _irq_gate_bc +public _irq_gate_bd +public _irq_gate_be +public _irq_gate_bf +public _irq_gate_c0 +public _irq_gate_c1 +public _irq_gate_c2 +public _irq_gate_c3 +public _irq_gate_c4 +public _irq_gate_c5 +public _irq_gate_c6 +public _irq_gate_c7 +public _irq_gate_c8 +public _irq_gate_c9 +public _irq_gate_ca +public _irq_gate_cb +public _irq_gate_cc +public _irq_gate_cd +public _irq_gate_ce +public _irq_gate_cf +public _irq_gate_d0 +public _irq_gate_d1 +public _irq_gate_d2 +public _irq_gate_d3 +public _irq_gate_d4 +public _irq_gate_d5 +public _irq_gate_d6 +public _irq_gate_d7 +public _irq_gate_d8 +public _irq_gate_d9 +public _irq_gate_da +public _irq_gate_db +public _irq_gate_dc +public _irq_gate_dd +public _irq_gate_de +public _irq_gate_df +public _irq_gate_e0 +public _irq_gate_e1 +public _irq_gate_e2 +public _irq_gate_e3 +public _irq_gate_e4 +public _irq_gate_e5 +public _irq_gate_e6 +public _irq_gate_e7 +public _irq_gate_e8 +public _irq_gate_e9 +public _irq_gate_ea +public _irq_gate_eb +public _irq_gate_ec +public _irq_gate_ed +public _irq_gate_ee +public _irq_gate_ef +public _irq_gate_f0 +public _irq_gate_f1 +public _irq_gate_f2 +public _irq_gate_f3 +public _irq_gate_f4 +public _irq_gate_f5 +public _irq_gate_f6 +public _irq_gate_f7 +public _irq_gate_f8 +public _irq_gate_f9 +public _irq_gate_fa +public _irq_gate_fb +public _irq_gate_fc +public _irq_gate_fd +public _irq_gate_fe + + +extrn exception_DE_event +extrn exception_DB_event +extrn exception_NMI_event +extrn exception_BP_event +extrn exception_OF_event +extrn exception_BR_event +extrn exception_UD_event +extrn exception_NM_event +extrn exception_DF_event +extrn exception_TS_event +extrn exception_NP_event +extrn exception_SS_event +extrn exception_GP_event +extrn exception_PF_event +extrn exception_MF_event +extrn exception_AC_event +extrn exception_MC_event +extrn exception_XF_event +extrn exception_SX_event +extrn exception_other_event + +extrn irq_timer_event +extrn irq_keyboard_event +extrn irq_other_event +extrn irq_handler_any + +macro SaveState +{ + sub esp, 256 + mov qword [esp+64], edi + mov qword [esp+72], esi + mov qword [esp+80], edx + mov qword [esp+88], ecx + mov qword [esp+96], ebx + mov qword [esp+104], eax + mov qword [esp+112], ebp + mov qword [esp+120], esp +} + +macro RestoreState +{ + mov edi, qword [esp+64] + mov esi, qword [esp+72] + mov edx, qword [esp+80] + mov ecx, qword [esp+88] + mov ebx, qword [esp+96] + mov eax, qword [esp+104] + mov ebp, qword [esp+112] + mov esp, qword [esp+120] + add esp, 256 +} + +macro IrqHandler num +{ + SaveState + mov edi, num + call irq_handler_any + RestoreState + iretq +} + +macro Hang +{ + jmp $ +} + +; edi containts first argument - stack pointer +; esi containts second argument - address to jump +_switch_to_stack: + + xor eax,eax + push eax ; target ss + push edi ; target esp + pushfq ; target flags + push eax ; target cs + push esi ; target rip + iretq + +; --------------------------------------------------- +; begin preempt logic + +; Param: edi - load thread structure location, 16 bytes aligned +; structure size - 1024 bytes +; 0 - 512 fx state +; 512 - 1024 general registers etc + +_enterFirstThread: + + xor eax, eax + push eax ; target ss + push qword [edi+560] ; target esp + pushfq ; target flags + push 0x08 ; target cs + push qword [edi+568] ; target rip + mov edi, qword [edi+576] ; pass thread pointer as 1st parameter + iretq + +; +; Param: edi - save thread structure location, 16 bytes aligned +; structure size - 1024 bytes +; 0 - 512 fx state +; 512 - 1024 general registers etc +; Param: esi - load thread structure location, 16 bytes aligned +; structure size - 1024 bytes +; 0 - 512 fx state +; 512 - 1024 general registers etc +; + +_preemptStart: + cli + push edi + fxsave [edi] + mov qword [edi+552], ebx + mov qword [edi+560], esp + mov qword [edi+568], _preemptCallback + + xor eax, eax + push eax ; target ss + push qword [esi+560] ; target esp + pushfq ; target flags + push 0x08 ; target cs + push qword [esi+568] ; target rip + mov edi, qword [esi+576] ; pass thread pointer as 1st parameter + iretq + +_preemptCallback: + pop edi + fxrstor [edi] + mov ebp, qword [edi+544] + mov ebx, qword [edi+552] + mov eax, qword [edi+576] ; return thread pointer + sti + ret + +; Param: edi - clean 1024 byte space for thread structure location +; Param: esi - function pointer to thread entry point +; Param: edx - thread stack location +; Param: ecx - thread object pointer + +_threadStructInit: + fxsave [edi] ; save current state, it could be any valid fxstate + xor eax, eax + mov qword [edi+512], eax + mov qword [edi+520], eax + mov qword [edi+528], eax + mov qword [edi+536], eax + mov qword [edi+544], eax + mov qword [edi+552], eax + mov qword [edi+560], edx + mov qword [edi+568], esi + mov qword [edi+576], ecx + ret + +; end preempt logic +; --------------------------------------------------- + +_int_gate_exception_DE: + + SaveState + call exception_DE_event + RestoreState + Hang + +_int_gate_exception_DB: + + SaveState + call exception_DB_event + RestoreState + Hang + +_int_gate_exception_NMI: + + SaveState + call exception_NMI_event + RestoreState + Hang + +_int_gate_exception_BP: + + SaveState + call exception_BP_event + RestoreState + Hang + +_int_gate_exception_OF: + + SaveState + call exception_OF_event + RestoreState + Hang + +_int_gate_exception_BR: + + SaveState + call exception_BR_event + RestoreState + Hang + +_int_gate_exception_UD: + + pop edi ; rip, 1 arg + pop esi ; cs, 2 arg + SaveState + call exception_UD_event + RestoreState + Hang + +_int_gate_exception_NM: + + SaveState + call exception_NM_event + RestoreState + Hang + +_int_gate_exception_DF: + + SaveState + call exception_DF_event + RestoreState + Hang + +_int_gate_exception_TS: + + SaveState + call exception_TS_event + RestoreState + Hang + +_int_gate_exception_NP: + + SaveState + call exception_NP_event + RestoreState + Hang + +_int_gate_exception_SS: + + SaveState + call exception_SS_event + RestoreState + Hang + +_int_gate_exception_GP: + + pop edx ; error code, 3arg + pop edi ; rip, 1 arg + pop esi ; cs, 2 arg + pop ebx ; remove flags + pop ebx ; remore esp + pop ebx ; remove ss + mov ecx, eax ; save eax, 4 arg + + SaveState + call exception_GP_event + RestoreState + cli + hlt + iretq + +_int_gate_exception_PF: + + SaveState + mov esi, 0 + mov edi, cr2 ; CR2 contians the address that the program tried to access + call exception_PF_event + RestoreState + add esp, 8 ; fix esp after state restore + iretq + +_int_gate_exception_MF: + + SaveState + call exception_MF_event + RestoreState + Hang + +_int_gate_exception_AC: + + SaveState + call exception_AC_event + RestoreState + Hang + +_int_gate_exception_MC: + + SaveState + call exception_MC_event + RestoreState + Hang + +_int_gate_exception_XF: + + SaveState + call exception_XF_event + RestoreState + Hang + +_int_gate_exception_SX: + + SaveState + call exception_SX_event + RestoreState + Hang + +_int_gate_exception_other: + + SaveState + call exception_other_event + RestoreState + Hang + +align 16 + +_int_gate_irq_timer: + + SaveState + mov edi, esp ; arg 0 + add edi, 256 + mov edx, [edi] ; arg 2, rip from stack + add edi, 40 ; compute sp, exclude cpu saved state (5*qword) + mov esi, ebp ; arg 1 + call irq_timer_event + RestoreState + iretq + +align 16 +_int_gate_irq_keyboard: + + ; debugging + ; pop edi ; place RIP into first argument + ; push edi ; put it back + + SaveState + call irq_keyboard_event + RestoreState + iretq + +align 16 +_irq_gate_20: IrqHandler 0x0 +_irq_gate_21: IrqHandler 0x1 +_irq_gate_22: IrqHandler 0x2 +_irq_gate_23: IrqHandler 0x3 +_irq_gate_24: IrqHandler 0x4 +_irq_gate_25: IrqHandler 0x5 +_irq_gate_26: IrqHandler 0x6 +_irq_gate_27: IrqHandler 0x7 +_irq_gate_28: IrqHandler 0x8 +_irq_gate_29: IrqHandler 0x9 +_irq_gate_2a: IrqHandler 0xa +_irq_gate_2b: IrqHandler 0xb +_irq_gate_2c: IrqHandler 0xc +_irq_gate_2d: IrqHandler 0xd +_irq_gate_2e: IrqHandler 0xe +_irq_gate_2f: IrqHandler 0xf +_irq_gate_30: IrqHandler 0x10 +_irq_gate_31: IrqHandler 0x11 +_irq_gate_32: IrqHandler 0x12 +_irq_gate_33: IrqHandler 0x13 +_irq_gate_34: IrqHandler 0x14 +_irq_gate_35: IrqHandler 0x15 +_irq_gate_36: IrqHandler 0x16 +_irq_gate_37: IrqHandler 0x17 +_irq_gate_38: IrqHandler 0x18 +_irq_gate_39: IrqHandler 0x19 +_irq_gate_3a: IrqHandler 0x1a +_irq_gate_3b: IrqHandler 0x1b +_irq_gate_3c: IrqHandler 0x1c +_irq_gate_3d: IrqHandler 0x1d +_irq_gate_3e: IrqHandler 0x1e +_irq_gate_3f: IrqHandler 0x1f +_irq_gate_40: IrqHandler 0x20 +_irq_gate_41: IrqHandler 0x21 +_irq_gate_42: IrqHandler 0x22 +_irq_gate_43: IrqHandler 0x23 +_irq_gate_44: IrqHandler 0x24 +_irq_gate_45: IrqHandler 0x25 +_irq_gate_46: IrqHandler 0x26 +_irq_gate_47: IrqHandler 0x27 +_irq_gate_48: IrqHandler 0x28 +_irq_gate_49: IrqHandler 0x29 +_irq_gate_4a: IrqHandler 0x2a +_irq_gate_4b: IrqHandler 0x2b +_irq_gate_4c: IrqHandler 0x2c +_irq_gate_4d: IrqHandler 0x2d +_irq_gate_4e: IrqHandler 0x2e +_irq_gate_4f: IrqHandler 0x2f +_irq_gate_50: IrqHandler 0x30 +_irq_gate_51: IrqHandler 0x31 +_irq_gate_52: IrqHandler 0x32 +_irq_gate_53: IrqHandler 0x33 +_irq_gate_54: IrqHandler 0x34 +_irq_gate_55: IrqHandler 0x35 +_irq_gate_56: IrqHandler 0x36 +_irq_gate_57: IrqHandler 0x37 +_irq_gate_58: IrqHandler 0x38 +_irq_gate_59: IrqHandler 0x39 +_irq_gate_5a: IrqHandler 0x3a +_irq_gate_5b: IrqHandler 0x3b +_irq_gate_5c: IrqHandler 0x3c +_irq_gate_5d: IrqHandler 0x3d +_irq_gate_5e: IrqHandler 0x3e +_irq_gate_5f: IrqHandler 0x3f +_irq_gate_60: IrqHandler 0x40 +_irq_gate_61: IrqHandler 0x41 +_irq_gate_62: IrqHandler 0x42 +_irq_gate_63: IrqHandler 0x43 +_irq_gate_64: IrqHandler 0x44 +_irq_gate_65: IrqHandler 0x45 +_irq_gate_66: IrqHandler 0x46 +_irq_gate_67: IrqHandler 0x47 +_irq_gate_68: IrqHandler 0x48 +_irq_gate_69: IrqHandler 0x49 +_irq_gate_6a: IrqHandler 0x4a +_irq_gate_6b: IrqHandler 0x4b +_irq_gate_6c: IrqHandler 0x4c +_irq_gate_6d: IrqHandler 0x4d +_irq_gate_6e: IrqHandler 0x4e +_irq_gate_6f: IrqHandler 0x4f +_irq_gate_70: IrqHandler 0x50 +_irq_gate_71: IrqHandler 0x51 +_irq_gate_72: IrqHandler 0x52 +_irq_gate_73: IrqHandler 0x53 +_irq_gate_74: IrqHandler 0x54 +_irq_gate_75: IrqHandler 0x55 +_irq_gate_76: IrqHandler 0x56 +_irq_gate_77: IrqHandler 0x57 +_irq_gate_78: IrqHandler 0x58 +_irq_gate_79: IrqHandler 0x59 +_irq_gate_7a: IrqHandler 0x5a +_irq_gate_7b: IrqHandler 0x5b +_irq_gate_7c: IrqHandler 0x5c +_irq_gate_7d: IrqHandler 0x5d +_irq_gate_7e: IrqHandler 0x5e +_irq_gate_7f: IrqHandler 0x5f +_irq_gate_80: IrqHandler 0x60 +_irq_gate_81: IrqHandler 0x61 +_irq_gate_82: IrqHandler 0x62 +_irq_gate_83: IrqHandler 0x63 +_irq_gate_84: IrqHandler 0x64 +_irq_gate_85: IrqHandler 0x65 +_irq_gate_86: IrqHandler 0x66 +_irq_gate_87: IrqHandler 0x67 +_irq_gate_88: IrqHandler 0x68 +_irq_gate_89: IrqHandler 0x69 +_irq_gate_8a: IrqHandler 0x6a +_irq_gate_8b: IrqHandler 0x6b +_irq_gate_8c: IrqHandler 0x6c +_irq_gate_8d: IrqHandler 0x6d +_irq_gate_8e: IrqHandler 0x6e +_irq_gate_8f: IrqHandler 0x6f +_irq_gate_90: IrqHandler 0x70 +_irq_gate_91: IrqHandler 0x71 +_irq_gate_92: IrqHandler 0x72 +_irq_gate_93: IrqHandler 0x73 +_irq_gate_94: IrqHandler 0x74 +_irq_gate_95: IrqHandler 0x75 +_irq_gate_96: IrqHandler 0x76 +_irq_gate_97: IrqHandler 0x77 +_irq_gate_98: IrqHandler 0x78 +_irq_gate_99: IrqHandler 0x79 +_irq_gate_9a: IrqHandler 0x7a +_irq_gate_9b: IrqHandler 0x7b +_irq_gate_9c: IrqHandler 0x7c +_irq_gate_9d: IrqHandler 0x7d +_irq_gate_9e: IrqHandler 0x7e +_irq_gate_9f: IrqHandler 0x7f +_irq_gate_a0: IrqHandler 0x80 +_irq_gate_a1: IrqHandler 0x81 +_irq_gate_a2: IrqHandler 0x82 +_irq_gate_a3: IrqHandler 0x83 +_irq_gate_a4: IrqHandler 0x84 +_irq_gate_a5: IrqHandler 0x85 +_irq_gate_a6: IrqHandler 0x86 +_irq_gate_a7: IrqHandler 0x87 +_irq_gate_a8: IrqHandler 0x88 +_irq_gate_a9: IrqHandler 0x89 +_irq_gate_aa: IrqHandler 0x8a +_irq_gate_ab: IrqHandler 0x8b +_irq_gate_ac: IrqHandler 0x8c +_irq_gate_ad: IrqHandler 0x8d +_irq_gate_ae: IrqHandler 0x8e +_irq_gate_af: IrqHandler 0x8f +_irq_gate_b0: IrqHandler 0x90 +_irq_gate_b1: IrqHandler 0x91 +_irq_gate_b2: IrqHandler 0x92 +_irq_gate_b3: IrqHandler 0x93 +_irq_gate_b4: IrqHandler 0x94 +_irq_gate_b5: IrqHandler 0x95 +_irq_gate_b6: IrqHandler 0x96 +_irq_gate_b7: IrqHandler 0x97 +_irq_gate_b8: IrqHandler 0x98 +_irq_gate_b9: IrqHandler 0x99 +_irq_gate_ba: IrqHandler 0x9a +_irq_gate_bb: IrqHandler 0x9b +_irq_gate_bc: IrqHandler 0x9c +_irq_gate_bd: IrqHandler 0x9d +_irq_gate_be: IrqHandler 0x9e +_irq_gate_bf: IrqHandler 0x9f +_irq_gate_c0: IrqHandler 0xa0 +_irq_gate_c1: IrqHandler 0xa1 +_irq_gate_c2: IrqHandler 0xa2 +_irq_gate_c3: IrqHandler 0xa3 +_irq_gate_c4: IrqHandler 0xa4 +_irq_gate_c5: IrqHandler 0xa5 +_irq_gate_c6: IrqHandler 0xa6 +_irq_gate_c7: IrqHandler 0xa7 +_irq_gate_c8: IrqHandler 0xa8 +_irq_gate_c9: IrqHandler 0xa9 +_irq_gate_ca: IrqHandler 0xaa +_irq_gate_cb: IrqHandler 0xab +_irq_gate_cc: IrqHandler 0xac +_irq_gate_cd: IrqHandler 0xad +_irq_gate_ce: IrqHandler 0xae +_irq_gate_cf: IrqHandler 0xaf +_irq_gate_d0: IrqHandler 0xb0 +_irq_gate_d1: IrqHandler 0xb1 +_irq_gate_d2: IrqHandler 0xb2 +_irq_gate_d3: IrqHandler 0xb3 +_irq_gate_d4: IrqHandler 0xb4 +_irq_gate_d5: IrqHandler 0xb5 +_irq_gate_d6: IrqHandler 0xb6 +_irq_gate_d7: IrqHandler 0xb7 +_irq_gate_d8: IrqHandler 0xb8 +_irq_gate_d9: IrqHandler 0xb9 +_irq_gate_da: IrqHandler 0xba +_irq_gate_db: IrqHandler 0xbb +_irq_gate_dc: IrqHandler 0xbc +_irq_gate_dd: IrqHandler 0xbd +_irq_gate_de: IrqHandler 0xbe +_irq_gate_df: IrqHandler 0xbf +_irq_gate_e0: IrqHandler 0xc0 +_irq_gate_e1: IrqHandler 0xc1 +_irq_gate_e2: IrqHandler 0xc2 +_irq_gate_e3: IrqHandler 0xc3 +_irq_gate_e4: IrqHandler 0xc4 +_irq_gate_e5: IrqHandler 0xc5 +_irq_gate_e6: IrqHandler 0xc6 +_irq_gate_e7: IrqHandler 0xc7 +_irq_gate_e8: IrqHandler 0xc8 +_irq_gate_e9: IrqHandler 0xc9 +_irq_gate_ea: IrqHandler 0xca +_irq_gate_eb: IrqHandler 0xcb +_irq_gate_ec: IrqHandler 0xcc +_irq_gate_ed: IrqHandler 0xcd +_irq_gate_ee: IrqHandler 0xce +_irq_gate_ef: IrqHandler 0xcf +_irq_gate_f0: IrqHandler 0xd0 +_irq_gate_f1: IrqHandler 0xd1 +_irq_gate_f2: IrqHandler 0xd2 +_irq_gate_f3: IrqHandler 0xd3 +_irq_gate_f4: IrqHandler 0xd4 +_irq_gate_f5: IrqHandler 0xd5 +_irq_gate_f6: IrqHandler 0xd6 +_irq_gate_f7: IrqHandler 0xd7 +_irq_gate_f8: IrqHandler 0xd8 +_irq_gate_f9: IrqHandler 0xd9 +_irq_gate_fa: IrqHandler 0xda +_irq_gate_fb: IrqHandler 0xdb +_irq_gate_fc: IrqHandler 0xdc +_irq_gate_fd: IrqHandler 0xdd +_irq_gate_fe: IrqHandler 0xde + + +_int_gate_irq_spurious: + iretq + +;------------------------------ +;EOF diff --git a/src/kernel/arch/x86/irqs-x86.cc b/src/kernel/arch/x86/irqs-x86.cc new file mode 100644 index 000000000..e8b35b951 --- /dev/null +++ b/src/kernel/arch/x86/irqs-x86.cc @@ -0,0 +1,598 @@ +// Copyright 2014 runtime.js project authors +// +// 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 +#include +#include +#include + +extern "C" { +#define GATE(NAME) uint64_t NAME() + GATE(int_gate_exception_DE); + GATE(int_gate_exception_DB); + GATE(int_gate_exception_NMI); + GATE(int_gate_exception_BP); + GATE(int_gate_exception_OF); + GATE(int_gate_exception_BR); + GATE(int_gate_exception_UD); + GATE(int_gate_exception_NM); + GATE(int_gate_exception_DF); + GATE(int_gate_exception_TS); + GATE(int_gate_exception_NP); + GATE(int_gate_exception_SS); + GATE(int_gate_exception_GP); + GATE(int_gate_exception_PF); + GATE(int_gate_exception_MF); + GATE(int_gate_exception_AC); + GATE(int_gate_exception_MC); + GATE(int_gate_exception_XF); + GATE(int_gate_exception_SX); + GATE(int_gate_exception_other); + GATE(int_gate_irq_timer); + GATE(int_gate_irq_keyboard); + GATE(int_gate_irq_other); + GATE(int_gate_irq_spurious); + GATE(gate_context_switch); + GATE(_irq_gate_20); + GATE(_irq_gate_21); + GATE(_irq_gate_22); + GATE(_irq_gate_23); + GATE(_irq_gate_24); + GATE(_irq_gate_25); + GATE(_irq_gate_26); + GATE(_irq_gate_27); + GATE(_irq_gate_28); + GATE(_irq_gate_29); + GATE(_irq_gate_2a); + GATE(_irq_gate_2b); + GATE(_irq_gate_2c); + GATE(_irq_gate_2d); + GATE(_irq_gate_2e); + GATE(_irq_gate_2f); + GATE(_irq_gate_30); + GATE(_irq_gate_31); + GATE(_irq_gate_32); + GATE(_irq_gate_33); + GATE(_irq_gate_34); + GATE(_irq_gate_35); + GATE(_irq_gate_36); + GATE(_irq_gate_37); + GATE(_irq_gate_38); + GATE(_irq_gate_39); + GATE(_irq_gate_3a); + GATE(_irq_gate_3b); + GATE(_irq_gate_3c); + GATE(_irq_gate_3d); + GATE(_irq_gate_3e); + GATE(_irq_gate_3f); + GATE(_irq_gate_40); + GATE(_irq_gate_41); + GATE(_irq_gate_42); + GATE(_irq_gate_43); + GATE(_irq_gate_44); + GATE(_irq_gate_45); + GATE(_irq_gate_46); + GATE(_irq_gate_47); + GATE(_irq_gate_48); + GATE(_irq_gate_49); + GATE(_irq_gate_4a); + GATE(_irq_gate_4b); + GATE(_irq_gate_4c); + GATE(_irq_gate_4d); + GATE(_irq_gate_4e); + GATE(_irq_gate_4f); + GATE(_irq_gate_50); + GATE(_irq_gate_51); + GATE(_irq_gate_52); + GATE(_irq_gate_53); + GATE(_irq_gate_54); + GATE(_irq_gate_55); + GATE(_irq_gate_56); + GATE(_irq_gate_57); + GATE(_irq_gate_58); + GATE(_irq_gate_59); + GATE(_irq_gate_5a); + GATE(_irq_gate_5b); + GATE(_irq_gate_5c); + GATE(_irq_gate_5d); + GATE(_irq_gate_5e); + GATE(_irq_gate_5f); + GATE(_irq_gate_60); + GATE(_irq_gate_61); + GATE(_irq_gate_62); + GATE(_irq_gate_63); + GATE(_irq_gate_64); + GATE(_irq_gate_65); + GATE(_irq_gate_66); + GATE(_irq_gate_67); + GATE(_irq_gate_68); + GATE(_irq_gate_69); + GATE(_irq_gate_6a); + GATE(_irq_gate_6b); + GATE(_irq_gate_6c); + GATE(_irq_gate_6d); + GATE(_irq_gate_6e); + GATE(_irq_gate_6f); + GATE(_irq_gate_70); + GATE(_irq_gate_71); + GATE(_irq_gate_72); + GATE(_irq_gate_73); + GATE(_irq_gate_74); + GATE(_irq_gate_75); + GATE(_irq_gate_76); + GATE(_irq_gate_77); + GATE(_irq_gate_78); + GATE(_irq_gate_79); + GATE(_irq_gate_7a); + GATE(_irq_gate_7b); + GATE(_irq_gate_7c); + GATE(_irq_gate_7d); + GATE(_irq_gate_7e); + GATE(_irq_gate_7f); + GATE(_irq_gate_80); + GATE(_irq_gate_81); + GATE(_irq_gate_82); + GATE(_irq_gate_83); + GATE(_irq_gate_84); + GATE(_irq_gate_85); + GATE(_irq_gate_86); + GATE(_irq_gate_87); + GATE(_irq_gate_88); + GATE(_irq_gate_89); + GATE(_irq_gate_8a); + GATE(_irq_gate_8b); + GATE(_irq_gate_8c); + GATE(_irq_gate_8d); + GATE(_irq_gate_8e); + GATE(_irq_gate_8f); + GATE(_irq_gate_90); + GATE(_irq_gate_91); + GATE(_irq_gate_92); + GATE(_irq_gate_93); + GATE(_irq_gate_94); + GATE(_irq_gate_95); + GATE(_irq_gate_96); + GATE(_irq_gate_97); + GATE(_irq_gate_98); + GATE(_irq_gate_99); + GATE(_irq_gate_9a); + GATE(_irq_gate_9b); + GATE(_irq_gate_9c); + GATE(_irq_gate_9d); + GATE(_irq_gate_9e); + GATE(_irq_gate_9f); + GATE(_irq_gate_a0); + GATE(_irq_gate_a1); + GATE(_irq_gate_a2); + GATE(_irq_gate_a3); + GATE(_irq_gate_a4); + GATE(_irq_gate_a5); + GATE(_irq_gate_a6); + GATE(_irq_gate_a7); + GATE(_irq_gate_a8); + GATE(_irq_gate_a9); + GATE(_irq_gate_aa); + GATE(_irq_gate_ab); + GATE(_irq_gate_ac); + GATE(_irq_gate_ad); + GATE(_irq_gate_ae); + GATE(_irq_gate_af); + GATE(_irq_gate_b0); + GATE(_irq_gate_b1); + GATE(_irq_gate_b2); + GATE(_irq_gate_b3); + GATE(_irq_gate_b4); + GATE(_irq_gate_b5); + GATE(_irq_gate_b6); + GATE(_irq_gate_b7); + GATE(_irq_gate_b8); + GATE(_irq_gate_b9); + GATE(_irq_gate_ba); + GATE(_irq_gate_bb); + GATE(_irq_gate_bc); + GATE(_irq_gate_bd); + GATE(_irq_gate_be); + GATE(_irq_gate_bf); + GATE(_irq_gate_c0); + GATE(_irq_gate_c1); + GATE(_irq_gate_c2); + GATE(_irq_gate_c3); + GATE(_irq_gate_c4); + GATE(_irq_gate_c5); + GATE(_irq_gate_c6); + GATE(_irq_gate_c7); + GATE(_irq_gate_c8); + GATE(_irq_gate_c9); + GATE(_irq_gate_ca); + GATE(_irq_gate_cb); + GATE(_irq_gate_cc); + GATE(_irq_gate_cd); + GATE(_irq_gate_ce); + GATE(_irq_gate_cf); + GATE(_irq_gate_d0); + GATE(_irq_gate_d1); + GATE(_irq_gate_d2); + GATE(_irq_gate_d3); + GATE(_irq_gate_d4); + GATE(_irq_gate_d5); + GATE(_irq_gate_d6); + GATE(_irq_gate_d7); + GATE(_irq_gate_d8); + GATE(_irq_gate_d9); + GATE(_irq_gate_da); + GATE(_irq_gate_db); + GATE(_irq_gate_dc); + GATE(_irq_gate_dd); + GATE(_irq_gate_de); + GATE(_irq_gate_df); + GATE(_irq_gate_e0); + GATE(_irq_gate_e1); + GATE(_irq_gate_e2); + GATE(_irq_gate_e3); + GATE(_irq_gate_e4); + GATE(_irq_gate_e5); + GATE(_irq_gate_e6); + GATE(_irq_gate_e7); + GATE(_irq_gate_e8); + GATE(_irq_gate_e9); + GATE(_irq_gate_ea); + GATE(_irq_gate_eb); + GATE(_irq_gate_ec); + GATE(_irq_gate_ed); + GATE(_irq_gate_ee); + GATE(_irq_gate_ef); + GATE(_irq_gate_f0); + GATE(_irq_gate_f1); + GATE(_irq_gate_f2); + GATE(_irq_gate_f3); + GATE(_irq_gate_f4); + GATE(_irq_gate_f5); + GATE(_irq_gate_f6); + GATE(_irq_gate_f7); + GATE(_irq_gate_f8); + GATE(_irq_gate_f9); + GATE(_irq_gate_fa); + GATE(_irq_gate_fb); + GATE(_irq_gate_fc); + GATE(_irq_gate_fd); + GATE(_irq_gate_fe); +#undef GATE +} // extern "C" + +namespace rt { + +void IrqsArch::DisableNMI() { + IoPortsX86::OutB(0x70, IoPortsX86::InB(0x70) | 0x80); +} + +void IrqsArch::EnableNMI() { + IoPortsX86::OutB(0x70, IoPortsX86::InB(0x70) & 0x7F); +} + +void IrqsArch::InstallGate(uint8_t vector, uint64_t (*func)(), uint8_t type) { + uint8_t* idt_table = (uint8_t*)kIDTTableBase; + uint8_t b[16]; + + b[0] = (uint64_t)func & 0x00000000000000FF; + b[1] = ((uint64_t)func & 0x000000000000FF00) >> 8; + b[2] = kCodeSelector; + b[3] = 0; + b[4] = 0; + b[5] = type; + b[6] = ((uint64_t)func & 0x0000000000FF0000) >> 16; + b[7] = ((uint64_t)func & 0x00000000FF000000) >> 24; + + b[8] = ((uint64_t)func & 0x000000FF00000000) >> 32; + b[9] = ((uint64_t)func & 0x0000FF0000000000) >> 40; + b[10] = ((uint64_t)func & 0x00FF000000000000) >> 48; + b[11] = ((uint64_t)func & 0xFF00000000000000) >> 56; + b[12] = 0; + b[13] = 0; + b[14] = 0; + b[15] = 0; + + for (uint32_t i = 0; i < 16; ++i) { + *(idt_table + vector * 16 + i) = b[i]; + } +} + +void IrqsArch::SetUp() { + DisableNMI(); + + // Remap IRQs + IoPortsX86::OutB(0x20, 0x11); // 00010001b, begin PIC 1 initialization + IoPortsX86::OutB(0xA0, 0x11); // 00010001b, begin PIC 2 initialization + + IoPortsX86::OutB(0x21, 0x20); // IRQ 0-7, interrupts 20h-27h + IoPortsX86::OutB(0xA1, 0x28); // IRQ 8-15, interrupts 28h-2Fh + + IoPortsX86::OutB(0x21, 0x04); + IoPortsX86::OutB(0xA1, 0x02); + + IoPortsX86::OutB(0x21, 0x01); + IoPortsX86::OutB(0xA1, 0x01); + + // Mask all PIC interrupts + IoPortsX86::OutB(0x21, 0xFF); + IoPortsX86::OutB(0xA1, 0xFF); + + // Gate type + uint8_t type = 0x8e; + + // Exceptions (0-31) + InstallGate(0x00, &int_gate_exception_DE, type); + InstallGate(0x01, &int_gate_exception_DB, type); + InstallGate(0x02, &int_gate_exception_NMI,type); + InstallGate(0x03, &int_gate_exception_BP, type); + InstallGate(0x04, &int_gate_exception_OF, type); + InstallGate(0x05, &int_gate_exception_BR, type); + InstallGate(0x06, &int_gate_exception_UD, type); + InstallGate(0x07, &int_gate_exception_NM, type); + InstallGate(0x08, &int_gate_exception_DF, type); + InstallGate(0x09, &int_gate_exception_other, type); + InstallGate(0x0A, &int_gate_exception_TS, type); + InstallGate(0x0B, &int_gate_exception_NP, type); + InstallGate(0x0C, &int_gate_exception_SS, type); + InstallGate(0x0D, &int_gate_exception_GP, type); + InstallGate(0x0E, &int_gate_exception_PF, type); + InstallGate(0x0F, &int_gate_exception_other, type); + InstallGate(0x10, &int_gate_exception_MF, type); + InstallGate(0x11, &int_gate_exception_AC, type); + InstallGate(0x12, &int_gate_exception_MC, type); + InstallGate(0x13, &int_gate_exception_XF, type); + InstallGate(0x14, &int_gate_exception_other, type); + InstallGate(0x15, &int_gate_exception_other, type); + InstallGate(0x16, &int_gate_exception_other, type); + InstallGate(0x17, &int_gate_exception_other, type); + InstallGate(0x18, &int_gate_exception_other, type); + InstallGate(0x19, &int_gate_exception_other, type); + InstallGate(0x1A, &int_gate_exception_other, type); + InstallGate(0x1B, &int_gate_exception_other, type); + InstallGate(0x1C, &int_gate_exception_other, type); + InstallGate(0x1D, &int_gate_exception_other, type); + InstallGate(0x1E, &int_gate_exception_SX, type); + InstallGate(0x1F, &int_gate_exception_other, type); + + // Special + InstallGate(0x20, &int_gate_irq_timer, type); + + // Other + InstallGate(0x21, &_irq_gate_21, type); + InstallGate(0x22, &int_gate_irq_timer, type); + InstallGate(0x23, &_irq_gate_23, type); + InstallGate(0x24, &_irq_gate_24, type); + InstallGate(0x25, &_irq_gate_25, type); + InstallGate(0x26, &_irq_gate_26, type); + InstallGate(0x27, &_irq_gate_27, type); + InstallGate(0x28, &_irq_gate_28, type); + InstallGate(0x29, &_irq_gate_29, type); + InstallGate(0x2a, &_irq_gate_2a, type); + InstallGate(0x2b, &_irq_gate_2b, type); + InstallGate(0x2c, &_irq_gate_2c, type); + InstallGate(0x2d, &_irq_gate_2d, type); + InstallGate(0x2e, &_irq_gate_2e, type); + InstallGate(0x2f, &_irq_gate_2f, type); + InstallGate(0x30, &_irq_gate_30, type); + InstallGate(0x31, &_irq_gate_31, type); + InstallGate(0x32, &_irq_gate_32, type); + InstallGate(0x33, &_irq_gate_33, type); + InstallGate(0x34, &_irq_gate_34, type); + InstallGate(0x35, &_irq_gate_35, type); + InstallGate(0x36, &_irq_gate_36, type); + InstallGate(0x37, &_irq_gate_37, type); + InstallGate(0x38, &_irq_gate_38, type); + InstallGate(0x39, &_irq_gate_39, type); + InstallGate(0x3a, &_irq_gate_3a, type); + InstallGate(0x3b, &_irq_gate_3b, type); + InstallGate(0x3c, &_irq_gate_3c, type); + InstallGate(0x3d, &_irq_gate_3d, type); + InstallGate(0x3e, &_irq_gate_3e, type); + InstallGate(0x3f, &_irq_gate_3f, type); + InstallGate(0x40, &_irq_gate_40, type); + InstallGate(0x41, &_irq_gate_41, type); + InstallGate(0x42, &_irq_gate_42, type); + InstallGate(0x43, &_irq_gate_43, type); + InstallGate(0x44, &_irq_gate_44, type); + InstallGate(0x45, &_irq_gate_45, type); + InstallGate(0x46, &_irq_gate_46, type); + InstallGate(0x47, &_irq_gate_47, type); + InstallGate(0x48, &_irq_gate_48, type); + InstallGate(0x49, &_irq_gate_49, type); + InstallGate(0x4a, &_irq_gate_4a, type); + InstallGate(0x4b, &_irq_gate_4b, type); + InstallGate(0x4c, &_irq_gate_4c, type); + InstallGate(0x4d, &_irq_gate_4d, type); + InstallGate(0x4e, &_irq_gate_4e, type); + InstallGate(0x4f, &_irq_gate_4f, type); + InstallGate(0x50, &_irq_gate_50, type); + InstallGate(0x51, &_irq_gate_51, type); + InstallGate(0x52, &_irq_gate_52, type); + InstallGate(0x53, &_irq_gate_53, type); + InstallGate(0x54, &_irq_gate_54, type); + InstallGate(0x55, &_irq_gate_55, type); + InstallGate(0x56, &_irq_gate_56, type); + InstallGate(0x57, &_irq_gate_57, type); + InstallGate(0x58, &_irq_gate_58, type); + InstallGate(0x59, &_irq_gate_59, type); + InstallGate(0x5a, &_irq_gate_5a, type); + InstallGate(0x5b, &_irq_gate_5b, type); + InstallGate(0x5c, &_irq_gate_5c, type); + InstallGate(0x5d, &_irq_gate_5d, type); + InstallGate(0x5e, &_irq_gate_5e, type); + InstallGate(0x5f, &_irq_gate_5f, type); + InstallGate(0x60, &_irq_gate_60, type); + InstallGate(0x61, &_irq_gate_61, type); + InstallGate(0x62, &_irq_gate_62, type); + InstallGate(0x63, &_irq_gate_63, type); + InstallGate(0x64, &_irq_gate_64, type); + InstallGate(0x65, &_irq_gate_65, type); + InstallGate(0x66, &_irq_gate_66, type); + InstallGate(0x67, &_irq_gate_67, type); + InstallGate(0x68, &_irq_gate_68, type); + InstallGate(0x69, &_irq_gate_69, type); + InstallGate(0x6a, &_irq_gate_6a, type); + InstallGate(0x6b, &_irq_gate_6b, type); + InstallGate(0x6c, &_irq_gate_6c, type); + InstallGate(0x6d, &_irq_gate_6d, type); + InstallGate(0x6e, &_irq_gate_6e, type); + InstallGate(0x6f, &_irq_gate_6f, type); + InstallGate(0x70, &_irq_gate_70, type); + InstallGate(0x71, &_irq_gate_71, type); + InstallGate(0x72, &_irq_gate_72, type); + InstallGate(0x73, &_irq_gate_73, type); + InstallGate(0x74, &_irq_gate_74, type); + InstallGate(0x75, &_irq_gate_75, type); + InstallGate(0x76, &_irq_gate_76, type); + InstallGate(0x77, &_irq_gate_77, type); + InstallGate(0x78, &_irq_gate_78, type); + InstallGate(0x79, &_irq_gate_79, type); + InstallGate(0x7a, &_irq_gate_7a, type); + InstallGate(0x7b, &_irq_gate_7b, type); + InstallGate(0x7c, &_irq_gate_7c, type); + InstallGate(0x7d, &_irq_gate_7d, type); + InstallGate(0x7e, &_irq_gate_7e, type); + InstallGate(0x7f, &_irq_gate_7f, type); + InstallGate(0x80, &_irq_gate_80, type); + InstallGate(0x81, &_irq_gate_81, type); + InstallGate(0x82, &_irq_gate_82, type); + InstallGate(0x83, &_irq_gate_83, type); + InstallGate(0x84, &_irq_gate_84, type); + InstallGate(0x85, &_irq_gate_85, type); + InstallGate(0x86, &_irq_gate_86, type); + InstallGate(0x87, &_irq_gate_87, type); + InstallGate(0x88, &_irq_gate_88, type); + InstallGate(0x89, &_irq_gate_89, type); + InstallGate(0x8a, &_irq_gate_8a, type); + InstallGate(0x8b, &_irq_gate_8b, type); + InstallGate(0x8c, &_irq_gate_8c, type); + InstallGate(0x8d, &_irq_gate_8d, type); + InstallGate(0x8e, &_irq_gate_8e, type); + InstallGate(0x8f, &_irq_gate_8f, type); + InstallGate(0x90, &_irq_gate_90, type); + InstallGate(0x91, &_irq_gate_91, type); + InstallGate(0x92, &_irq_gate_92, type); + InstallGate(0x93, &_irq_gate_93, type); + InstallGate(0x94, &_irq_gate_94, type); + InstallGate(0x95, &_irq_gate_95, type); + InstallGate(0x96, &_irq_gate_96, type); + InstallGate(0x97, &_irq_gate_97, type); + InstallGate(0x98, &_irq_gate_98, type); + InstallGate(0x99, &_irq_gate_99, type); + InstallGate(0x9a, &_irq_gate_9a, type); + InstallGate(0x9b, &_irq_gate_9b, type); + InstallGate(0x9c, &_irq_gate_9c, type); + InstallGate(0x9d, &_irq_gate_9d, type); + InstallGate(0x9e, &_irq_gate_9e, type); + InstallGate(0x9f, &_irq_gate_9f, type); + InstallGate(0xa0, &_irq_gate_a0, type); + InstallGate(0xa1, &_irq_gate_a1, type); + InstallGate(0xa2, &_irq_gate_a2, type); + InstallGate(0xa3, &_irq_gate_a3, type); + InstallGate(0xa4, &_irq_gate_a4, type); + InstallGate(0xa5, &_irq_gate_a5, type); + InstallGate(0xa6, &_irq_gate_a6, type); + InstallGate(0xa7, &_irq_gate_a7, type); + InstallGate(0xa8, &_irq_gate_a8, type); + InstallGate(0xa9, &_irq_gate_a9, type); + InstallGate(0xaa, &_irq_gate_aa, type); + InstallGate(0xab, &_irq_gate_ab, type); + InstallGate(0xac, &_irq_gate_ac, type); + InstallGate(0xad, &_irq_gate_ad, type); + InstallGate(0xae, &_irq_gate_ae, type); + InstallGate(0xaf, &_irq_gate_af, type); + InstallGate(0xb0, &_irq_gate_b0, type); + InstallGate(0xb1, &_irq_gate_b1, type); + InstallGate(0xb2, &_irq_gate_b2, type); + InstallGate(0xb3, &_irq_gate_b3, type); + InstallGate(0xb4, &_irq_gate_b4, type); + InstallGate(0xb5, &_irq_gate_b5, type); + InstallGate(0xb6, &_irq_gate_b6, type); + InstallGate(0xb7, &_irq_gate_b7, type); + InstallGate(0xb8, &_irq_gate_b8, type); + InstallGate(0xb9, &_irq_gate_b9, type); + InstallGate(0xba, &_irq_gate_ba, type); + InstallGate(0xbb, &_irq_gate_bb, type); + InstallGate(0xbc, &_irq_gate_bc, type); + InstallGate(0xbd, &_irq_gate_bd, type); + InstallGate(0xbe, &_irq_gate_be, type); + InstallGate(0xbf, &_irq_gate_bf, type); + InstallGate(0xc0, &_irq_gate_c0, type); + InstallGate(0xc1, &_irq_gate_c1, type); + InstallGate(0xc2, &_irq_gate_c2, type); + InstallGate(0xc3, &_irq_gate_c3, type); + InstallGate(0xc4, &_irq_gate_c4, type); + InstallGate(0xc5, &_irq_gate_c5, type); + InstallGate(0xc6, &_irq_gate_c6, type); + InstallGate(0xc7, &_irq_gate_c7, type); + InstallGate(0xc8, &_irq_gate_c8, type); + InstallGate(0xc9, &_irq_gate_c9, type); + InstallGate(0xca, &_irq_gate_ca, type); + InstallGate(0xcb, &_irq_gate_cb, type); + InstallGate(0xcc, &_irq_gate_cc, type); + InstallGate(0xcd, &_irq_gate_cd, type); + InstallGate(0xce, &_irq_gate_ce, type); + InstallGate(0xcf, &_irq_gate_cf, type); + InstallGate(0xd0, &_irq_gate_d0, type); + InstallGate(0xd1, &_irq_gate_d1, type); + InstallGate(0xd2, &_irq_gate_d2, type); + InstallGate(0xd3, &_irq_gate_d3, type); + InstallGate(0xd4, &_irq_gate_d4, type); + InstallGate(0xd5, &_irq_gate_d5, type); + InstallGate(0xd6, &_irq_gate_d6, type); + InstallGate(0xd7, &_irq_gate_d7, type); + InstallGate(0xd8, &_irq_gate_d8, type); + InstallGate(0xd9, &_irq_gate_d9, type); + InstallGate(0xda, &_irq_gate_da, type); + InstallGate(0xdb, &_irq_gate_db, type); + InstallGate(0xdc, &_irq_gate_dc, type); + InstallGate(0xdd, &_irq_gate_dd, type); + InstallGate(0xde, &_irq_gate_de, type); + InstallGate(0xdf, &_irq_gate_df, type); + InstallGate(0xe0, &_irq_gate_e0, type); + InstallGate(0xe1, &_irq_gate_e1, type); + InstallGate(0xe2, &_irq_gate_e2, type); + InstallGate(0xe3, &_irq_gate_e3, type); + InstallGate(0xe4, &_irq_gate_e4, type); + InstallGate(0xe5, &_irq_gate_e5, type); + InstallGate(0xe6, &_irq_gate_e6, type); + InstallGate(0xe7, &_irq_gate_e7, type); + InstallGate(0xe8, &_irq_gate_e8, type); + InstallGate(0xe9, &_irq_gate_e9, type); + InstallGate(0xea, &_irq_gate_ea, type); + InstallGate(0xeb, &_irq_gate_eb, type); + InstallGate(0xec, &_irq_gate_ec, type); + InstallGate(0xed, &_irq_gate_ed, type); + InstallGate(0xee, &_irq_gate_ee, type); + InstallGate(0xef, &_irq_gate_ef, type); + InstallGate(0xf0, &_irq_gate_f0, type); + InstallGate(0xf1, &_irq_gate_f1, type); + InstallGate(0xf2, &_irq_gate_f2, type); + InstallGate(0xf3, &_irq_gate_f3, type); + InstallGate(0xf4, &_irq_gate_f4, type); + InstallGate(0xf5, &_irq_gate_f5, type); + InstallGate(0xf6, &_irq_gate_f6, type); + InstallGate(0xf7, &_irq_gate_f7, type); + InstallGate(0xf8, &_irq_gate_f8, type); + InstallGate(0xf9, &_irq_gate_f9, type); + InstallGate(0xfa, &_irq_gate_fa, type); + InstallGate(0xfb, &_irq_gate_fb, type); + InstallGate(0xfc, &_irq_gate_fc, type); + InstallGate(0xfd, &_irq_gate_fd, type); + InstallGate(0xfe, &_irq_gate_fe, type); + + // Spurious + InstallGate(0xff, &int_gate_irq_spurious, type); +} + +} // namespace rt diff --git a/src/kernel/arch/x86/irqs-x86.h b/src/kernel/arch/x86/irqs-x86.h new file mode 100644 index 000000000..19637e2a0 --- /dev/null +++ b/src/kernel/arch/x86/irqs-x86.h @@ -0,0 +1,35 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once +#include +#include + +namespace rt { + +class IrqsArch { +public: + IrqsArch() {} + void SetUp(); +private: + void DisableNMI(); + void EnableNMI(); + void InstallGate(uint8_t vector, uint64_t (*func)(), uint8_t type); + + static const uint64_t kIDTTableBase = 0; + static const uint8_t kCodeSelector = 0x8; + DELETE_COPY_AND_ASSIGN(IrqsArch); +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/local-apic-x86.cc b/src/kernel/arch/x86/local-apic-x86.cc new file mode 100644 index 000000000..7dbc82f11 --- /dev/null +++ b/src/kernel/arch/x86/local-apic-x86.cc @@ -0,0 +1,126 @@ +// Copyright 2014 runtime.js project authors +// +// 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 "local-apic-x86.h" +#include +#include +#include +#include +#include +#include + +namespace rt { + +LocalApicX86::LocalApicX86(void* local_apic_address) + : local_apic_address_(local_apic_address), + registers_(local_apic_address), + bus_freq_(0) { + RT_ASSERT(local_apic_address); +} + +void LocalApicX86::CpuSetAPICBase(uintptr_t apic) { + uint32_t edx = (apic >> 32) & 0x0f; + uint32_t eax = (apic & 0xfffff100) | kApicBaseMSREnable; + + CpuMSRValue value(eax, edx); + CpuPlatform::SetMSR(kApicBaseMSR, value); +} + +uintptr_t LocalApicX86::CpuGetAPICBase() { + auto value = CpuPlatform::GetMSR(kApicBaseMSR); + return (value.lo & 0xfffff100) | ((uintptr_t)(value.hi & 0x0f) << 32); +} + +void LocalApicX86::InitCpu(PlatformArch* platform) { + RT_ASSERT(platform); + + GLOBAL_mem_manager()->address_space().MapPage( + local_apic_address_, + local_apic_address_, true, true); + + CpuSetAPICBase(CpuGetAPICBase()); + + // Clear task priority to enable all interrupts + registers_.Write(LocalApicRegister::TASK_PRIORITY, 0); + + // Set masks + registers_.Write(LocalApicRegister::LINT0, 1 << 16); + registers_.Write(LocalApicRegister::LINT1, 1 << 16); + registers_.Write(LocalApicRegister::TIMER, 1 << 16); + + // Perf + registers_.Write(LocalApicRegister::PERF, 4 << 8); + + // Flat mode + registers_.Write(LocalApicRegister::DESTINATION_FORMAT, 0xffffffff); + + // Logical Destination Mode, all cpus use logical id 1 + registers_.Write(LocalApicRegister::LOGICAL_DESTINATION, 1); + + // Configure Spurious Interrupt Vector Register + registers_.Write(LocalApicRegister::SPURIOUS_INTERRUPT_VECTOR, 0x100 | 0xff); + + uint8_t timer_vector = 32; + + if (0 == bus_freq_) { + // Ensure we do this once on CPU 0 + RT_ASSERT(0 == Cpu::id()); + + // Calibrate times + registers_.Write(LocalApicRegister::TIMER, timer_vector); + registers_.Write(LocalApicRegister::TIMER_DIVIDE_CONFIG, 0x03); + + uint64_t start = platform->BootTimeMicroseconds(); + + // Reset APIC timer (set counter to -1) + registers_.Write(LocalApicRegister::TIMER_INITIAL_COUNT, 0xffffffffU); + + // 1/100 of a second + while (platform->BootTimeMicroseconds() - start < 10000) { + Cpu::WaitPause(); + } + + // Stop Apic timer + registers_.Write(LocalApicRegister::TIMER, 1 << 16); + + // Calculate bus frequency + uint32_t curr_count = registers_.Read(LocalApicRegister::TIMER_CURRENT_COUNT); + uint32_t cpubusfreq = ((0xFFFFFFFF - curr_count) + 1) * 16 * 100; + bus_freq_ = cpubusfreq; + } + + RT_ASSERT(bus_freq_); + uint32_t quantum = 32; +#ifdef RUNTIME_PROFILER + quantum = 4096 * 4; +#endif + uint32_t init_count = bus_freq_ / quantum / 16; + + // Set minimum initial count value to avoid QEMU + // "I/O thread has spun for 1000 iterations" warning + if (init_count < 0x1000) { + init_count = 0x1000; + } + + // Set periodic mode for APIC timer + registers_.Write(LocalApicRegister::TIMER_INITIAL_COUNT, init_count); + registers_.Write(LocalApicRegister::TIMER, timer_vector | 0x20000); + registers_.Write(LocalApicRegister::TIMER_DIVIDE_CONFIG, 0x03); + + registers_.Read(LocalApicRegister::SPURIOUS_INTERRUPT_VECTOR); + + EOI(); +} + +} // namespace rt diff --git a/src/kernel/arch/x86/local-apic-x86.h b/src/kernel/arch/x86/local-apic-x86.h new file mode 100644 index 000000000..c7d9e2c7d --- /dev/null +++ b/src/kernel/arch/x86/local-apic-x86.h @@ -0,0 +1,205 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace rt { + +class PlatformArch; + +/** + * List of available local apic registers + */ +enum class LocalApicRegister { + ID = 0x0020, // Local APIC ID + VERSION = 0x0030, // Local APIC Version + TASK_PRIORITY = 0x0080, // Task Priority + ARBITRATION_PRIORITY = 0x0090, // Arbitration Priority + PROCESSOR_PRIORITY = 0x00a0, // Processor Priority + EOI = 0x00b0, // EOI + RRD = 0x00c0, // Remote Read + LOGICAL_DESTINATION = 0x00d0, // Logical Destination + DESTINATION_FORMAT = 0x00e0, // Destination Format + SPURIOUS_INTERRUPT_VECTOR = 0x00f0, // Spurious Interrupt Vector + ISR = 0x0100, // In-Service (8 registers) + TMR = 0x0180, // Trigger Mode (8 registers) + IRR = 0x0200, // Interrupt Request (8 registers) + ERROR_STATUS = 0x0280, // Error Status + INTERRUPT_COMMAND_LO = 0x0300, // Interrupt Command (writing here sends command) + INTERRUPT_COMMAND_HI = 0x0310, // Interrupt Command [63:32] + TIMER = 0x0320, // LVT Timer + THERMAL = 0x0330, // LVT Thermal Sensor + PERF = 0x0340, // LVT Performance Counter + LINT0 = 0x0350, // LVT LINT0 + LINT1 = 0x0360, // LVT LINT1 + ERROR = 0x0370, // LVT Error + TIMER_INITIAL_COUNT = 0x0380, // Initial Count (for Timer) + TIMER_CURRENT_COUNT = 0x0390, // Current Count (for Timer) + TIMER_DIVIDE_CONFIG = 0x03e0 // Divide Configuration (for Timer) +}; + +/** + * Local apic command object + */ +class LocalApicInterruptCommand { + friend class LocalApicRegisterAccessor; +public: + enum class DeliveryMode { + FIXED = 0, + LOWEST_PRIORITY = 1, + SMI = 2, + NMI = 4, + INIT = 5, + STARTUP = 6 + }; + + enum class DestinationMode { + PHYSICAL = 0, + LOGICAL = 1 + }; + + enum class DeliveryStatus { + IDLE = 0, + PENDING = 1 + }; + + enum class DestinationShorthand { + NONE = 0, + SELF = 1, + ALL = 2, + ALL_EXCEPT_SELF = 3 + }; + + LocalApicInterruptCommand(uint8_t vector_num, + DeliveryMode dmode, + DestinationMode destmode, + bool is_no_deassert, + bool trigger_mode, + DestinationShorthand dshort, + uint8_t dest) : + hi_(dest << 24), + lo_(vector_num | + (static_cast(dmode) << 8) | + (static_cast(destmode) << 11) | + (static_cast(is_no_deassert) << 14) | + (static_cast(trigger_mode) << 15) | + (static_cast(dshort) << 18)) {} +private: + uint32_t hi_; + uint32_t lo_; +}; + +/** + * Provides access to local apic registers + */ +class LocalApicRegisterAccessor { +public: + LocalApicRegisterAccessor(void* local_apic_base) : + local_apic_base_(static_cast(local_apic_base)) { + RT_ASSERT(local_apic_base); + } + + inline uint32_t Read(LocalApicRegister reg) { + return *(volatile uint32_t*)(local_apic_base_ + static_cast(reg)); + } + + inline void Write(LocalApicRegister reg, uint32_t value) { + *(volatile uint32_t*)(local_apic_base_ + static_cast(reg)) = value; + } + + inline void InterruptCommand(LocalApicInterruptCommand command) { + Write(LocalApicRegister::INTERRUPT_COMMAND_HI, command.hi_); + Write(LocalApicRegister::INTERRUPT_COMMAND_LO, command.lo_); + } + +private: + uint8_t* local_apic_base_; +}; + +class LocalApicX86 { +public: + LocalApicX86(void* local_apic_address); + + /** + * Send INIT command + */ + void SendApicInit(uint8_t apicid) { + registers_.InterruptCommand(LocalApicInterruptCommand( + 0, + LocalApicInterruptCommand::DeliveryMode::INIT, + LocalApicInterruptCommand::DestinationMode::PHYSICAL, + true, + false, + LocalApicInterruptCommand::DestinationShorthand::NONE, + apicid + )); + } + + /** + * Send STARTUP command + */ + void SendApicStartup(uint8_t apicid, uint8_t vector_num) { + registers_.InterruptCommand(LocalApicInterruptCommand( + vector_num, + LocalApicInterruptCommand::DeliveryMode::STARTUP, + LocalApicInterruptCommand::DestinationMode::PHYSICAL, + true, + false, + LocalApicInterruptCommand::DestinationShorthand::NONE, + apicid + )); + } + + /** + * Set EOI (End Of Interrupt) flag. Interrupt handler must + * do it before IRETQ + */ + void EOI() { + registers_.Write(LocalApicRegister::EOI, 0); + } + + /** + * Read Local Apic ID + */ + uint32_t Id() { + return registers_.Read(LocalApicRegister::ID); + } + + uint32_t bus_frequency() const { + return bus_freq_; + } + + void CpuSetAPICBase(uintptr_t apic); + uintptr_t CpuGetAPICBase(); + + void InitCpu(PlatformArch* platform); +private: + static const int kApicBaseMSR = 0x1b; + static const int kApicBaseMSREnable = 0x800; + + void* local_apic_address_; + LocalApicRegisterAccessor registers_; + uint32_t bus_freq_; + ~LocalApicX64() = delete; + DELETE_COPY_AND_ASSIGN(LocalApicX64); +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/platform-x86.cc b/src/kernel/arch/x86/platform-x86.cc new file mode 100644 index 000000000..8e0f39cea --- /dev/null +++ b/src/kernel/arch/x86/platform-x86.cc @@ -0,0 +1,54 @@ +// Copyright 2014 runtime.js project authors +// +// 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 +#include +#include +#include + +namespace rt { + +void PlatformArch::StartCPUs() { + acpi_.StartCPUs(); +} + +void PlatformArch::InitCurrentCPU() { + if (0 == Cpu::id()) { + acpi_.InitIoApics(); + } + + RT_ASSERT(acpi_.local_apic()); + acpi_.local_apic()->InitCpu(this); +} + +void PlatformArch::AckIRQ() { + RT_ASSERT(acpi_.local_apic()); + acpi_.local_apic()->EOI(); +} + +void PlatformArch::Reboot() { + const uint8_t magic = 0x02; + const uint16_t port = 0x64; + + uint8_t value = magic; + while (value & magic) { + value = IoPortsX64::InB(port); + } + + IoPortsX64::OutB(port, 0xfe); + Cpu::HangSystem(); +} + +} // namespace rt + diff --git a/src/kernel/arch/x86/platform-x86.h b/src/kernel/arch/x86/platform-x86.h new file mode 100644 index 000000000..15d57d44f --- /dev/null +++ b/src/kernel/arch/x86/platform-x86.h @@ -0,0 +1,53 @@ +// Copyright 2014 runtime.js project authors +// +// 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. + +#pragma once +#include +#include +#include + +namespace rt { + +class PlatformArch { +public: + PlatformArch() { + } + + void InitCurrentCPU(); + void StartCPUs(); + void AckIRQ(); + + /** + * Reboot machine using keyboard controller + */ + void Reboot(); + + uint32_t cpu_count() const { + return acpi_.cpus_count(); + } + + uint32_t bus_frequency() const { + RT_ASSERT(acpi_.local_apic()); + return acpi_.local_apic()->bus_frequency(); + } + + uint64_t BootTimeMicroseconds() const { + return acpi_.BootTimeMicroseconds(); + } +private: + AcpiX64 acpi_; + DELETE_COPY_AND_ASSIGN(PlatformArch); +}; + +} // namespace rt diff --git a/src/kernel/arch/x86/startup.asm b/src/kernel/arch/x86/startup.asm new file mode 100644 index 000000000..c0ba76ff7 --- /dev/null +++ b/src/kernel/arch/x86/startup.asm @@ -0,0 +1,146 @@ +; Copyright 2014 runtime.js project authors +; +; 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. + +format ELF64 + +THIS_LOADER_LOCATION = 0x200000 + +section ".loader" +use32 +org THIS_LOADER_LOCATION + +;===================================================== +; Constants +;===================================================== + +include 'startup_conf.inc' + +;===================================================== +; Multiboot structure +;===================================================== + +_header: + +dd MULTIBOOT_HEADER_MAGIC ; Magic +dd MULTIBOOT_HEADER_FLAGS ; Flags +dd -MULTIBOOT_HEADER_MAGIC-MULTIBOOT_HEADER_FLAGS ; Checksum +dd _header ; Header address +dd _header ; Data and Code start address +;dd _datacode_end ; Data and Code end address +;dd _end ; BSS end address +dd MULTIBOOT_LOAD_DATACODE_LEN +dd MULTIBOOT_LOAD_DATACODEBSS_LEN +dd _entry ; Entry address +dd 0 ;mode_type +dd 0 ;width +dd 0 ;height +dd 0 ;depth + +;===================================================== +; Code +;===================================================== + +_entry: + +; Check loader (multiboot?) + cmp eax, MULTIBOOT_LOADED_MAGIC + jnz not_multiboot_loaded + +; Save multiboot location + mov dword [mbt], ebx + +; Set 32bit stack + mov esp, SYSTEM_STACK_32BIT + +; Clear out the 4096 bytes of memory for 64-bit IDT + mov ecx, 1024 + xor eax, eax + mov edi, SYSTEM_IDT_TABLE_ADDR_64_32len + rep stosd + +; Clear memory for the Page Descriptor Entries + mov edi, 0x00020000 + mov ecx, 65536 + rep stosd + +; Copy the GDT to its final location in memory + mov esi, gdt64 + mov edi, SYSTEM_GDT_TABLE_ADDR_64_32len ; GDT address + mov ecx, (gdt64_end - gdt64) + rep movsb ; Move it + +; Create a PML4 entry + cld + mov edi, PAGING_PML4_ADDR + mov eax, PAGING_PDP_ADDR+PAGING_PDP_OPTIONS + stosd + xor eax, eax + stosd + +; Single PDP entry can map 1GiB with 2MB pages + mov ecx, PAGING_PDP_COUNT + mov edi, PAGING_PDP_ADDR + mov eax, PAGING_PD_ADDR+PAGING_PD_OPTIONS + +mkpdpe: + stosd + push eax + xor eax, eax + stosd + pop eax + add eax, 0x00001000 + dec ecx + cmp ecx, 0 + jne mkpdpe + +; Create the PD entries + mov edi, PAGING_PD_ADDR + mov eax, PAGING_PHYS_PAGE_OPTIONS + xor ecx, ecx + +mkpd: + stosd + push eax + xor eax, eax + stosd + pop eax + add eax, 0x00200000 + inc ecx + cmp ecx, PAGING_PD_COUNT + jne mkpd + +; Set current cpu #0 (BSP) + xor ax, ax + mov gs, ax + +; Init system +include 'startup_init.inc' + +use32 +not_multiboot_loaded: + mov eax, 'N M ' + mov [0x000B8000], eax + jmp $ + +;===================================================== +; BSS Section. No more data or code below +;===================================================== +_datacode_end: +;===================================================== +; End of segments (nothing except label below) +;===================================================== +_end: +;===================================================== +; EOF +;===================================================== diff --git a/src/kernel/arch/x86/startup_conf.inc b/src/kernel/arch/x86/startup_conf.inc new file mode 100644 index 000000000..6d094f147 --- /dev/null +++ b/src/kernel/arch/x86/startup_conf.inc @@ -0,0 +1,60 @@ +; Copyright 2014 runtime.js project authors +; +; 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. + +; MULTIBOOT +MULTIBOOT_HEADER_MAGIC = 0x1BADB002 +MULTIBOOT_PAGE_ALIGN = 1 shl 0 +MULTIBOOT_MEMORY_INFO = 1 shl 1 +MULTIBOOT_VIDEO_INFO = 1 shl 2 +MULTIBOOT_AOUT_KLUDGE = 1 shl 16 +MULTIBOOT_HEADER_FLAGS = MULTIBOOT_PAGE_ALIGN or MULTIBOOT_MEMORY_INFO or MULTIBOOT_AOUT_KLUDGE +MULTIBOOT_LOADED_MAGIC = 0x2BADB002 +MULTIBOOT_STRUCTURE_NEWLOC = 0x120000 +MULTIBOOT_STRUCTURE_MEMORY_NEWLOC = 0x121000 + +MULTIBOOT_LOAD_DATACODE_LEN = 0 +MULTIBOOT_LOAD_DATACODEBSS_LEN = 0 + +; SYSTEM VARS +SYSTEM_IDT_TABLE_ADDR_32 = 0x0000000000000000 +SYSTEM_IDT_TABLE_ADDR_32_32len = 0x00000000 ; same but 32 bit +SYSTEM_IDT_COUNT = 256 +SYSTEM_IDT_LEN_BYTES = 16 + +SYSTEM_GDT_TABLE_ADDR_32 = 0x0000000000001000 +SYSTEM_GDT_TABLE_ADDR_32_32len = 0x00001000 ; same but 32 bit + +; STACK AT 22 MiB +SYSTEM_STACK_32BIT = 0x1600000 +SYSTEM_STACK_64BIT = 0x1600000 + +;PAGING +PAGING_PML4_ADDR = 0x00002000 +PAGING_PML4_OPTIONS = 0x8 + +PAGING_PDP_COUNT = 1 +PAGING_PDP_ADDR = 0x00003000 +PAGING_PDP_OPTIONS = 0x7 + +PAGING_PD_COUNT = 512 +PAGING_PD_ADDR = 0x00020000 +PAGING_PD_OPTIONS = 0x7 + +PAGING_PHYS_PAGE_OPTIONS = 0x0000008F + +; 0x00002000 PML4#1 ---| +; 0x00003000 PDP#1 <--| +; ... +; 0x00020000 PD#1 +; ... diff --git a/src/kernel/arch/x86/startup_init.inc b/src/kernel/arch/x86/startup_init.inc new file mode 100644 index 000000000..beffd2984 --- /dev/null +++ b/src/kernel/arch/x86/startup_init.inc @@ -0,0 +1,60 @@ +; Copyright 2014 runtime.js project authors +; +; 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. + +; 32 bit mode +use32 + +; Enable CR4.PAE (bit 5) + mov eax, cr4 + or eax, 0x000000020 + mov cr4, eax + +; Setup CR3, write PML4 location + mov eax, PAGING_PML4_ADDR+PAGING_PML4_OPTIONS + mov cr3, eax + +; Enable long mode (EFER.LME=1) + mov ecx, 0xC0000080 + rdmsr + or eax, 0x00000100 + wrmsr + +; Enable paging, this will activate long mode + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + finit + + xor edi, edi + mov edi, dword [mbt] + jmp 0x201000 + +; Guard + jmp $ + +;===================================================== +; Data +;===================================================== +_data: + +align 16 +value_37F: dw 0x37F +value_37E: dw 0x37E +value_37A: dw 0x37A +mbt: dd 0 + +align 16 +IDTR32: + dw SYSTEM_IDT_COUNT*SYSTEM_IDT_LEN_BYTES-1 + dq SYSTEM_IDT_TABLE_ADDR_32 \ No newline at end of file diff --git a/src/kernel/kernel-main.cc b/src/kernel/boot/kernel-main.cc similarity index 98% rename from src/kernel/kernel-main.cc rename to src/kernel/boot/kernel-main.cc index 0bfc36a85..b9bd50df4 100644 --- a/src/kernel/kernel-main.cc +++ b/src/kernel/boot/kernel-main.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,7 @@ DEFINE_GLOBAL_OBJECT(GLOBAL_keystorage, rt::KeyStorage); DEFINE_GLOBAL_OBJECT(GLOBAL_initrd, rt::Initrd); DEFINE_GLOBAL_OBJECT(GLOBAL_engines, rt::Engines); DEFINE_GLOBAL_OBJECT(GLOBAL_trace, rt::Trace); +DEFINE_GLOBAL_OBJECT(GLOBAL_cpu, rt::Cpu); #undef DEFINE_GLOBAL_OBJECT @@ -200,7 +202,7 @@ void KernelMain::InitSystemBSP(void* mbt) { GLOBAL_engines()->Startup(); // Uncomment to enable SMP - // GLOBAL_platform()->StartCPUs(); + //if(cpus_found > 0) GLOBAL_platform()->StartCPUs(); } void KernelMain::InitSystemAP() { diff --git a/src/main.cc b/src/kernel/boot/main.cc similarity index 100% rename from src/main.cc rename to src/kernel/boot/main.cc diff --git a/src/kernel/multiboot.cc b/src/kernel/boot/multiboot.cc similarity index 98% rename from src/kernel/multiboot.cc rename to src/kernel/boot/multiboot.cc index d3ed92e02..4b65000a2 100644 --- a/src/kernel/multiboot.cc +++ b/src/kernel/boot/multiboot.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "multiboot.h" +#include #include #include diff --git a/src/startup.cc b/src/kernel/boot/startup.cc similarity index 100% rename from src/startup.cc rename to src/kernel/boot/startup.cc diff --git a/src/kernel/dlmalloc.cc b/src/kernel/dlmalloc.cc index 82f07d89c..58d7569b5 100644 --- a/src/kernel/dlmalloc.cc +++ b/src/kernel/dlmalloc.cc @@ -776,7 +776,7 @@ extern "C" int getpagesize(void) /* #define HAVE_USR_INCLUDE_MALLOC_H */ #ifdef HAVE_USR_INCLUDE_MALLOC_H -#include "/usr/include/malloc.h" +#include #else /* HAVE_USR_INCLUDE_MALLOC_H */ #ifndef STRUCT_MALLINFO_DECLARED /* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ @@ -1447,7 +1447,7 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int); ======================================================================== */ -/* #include "malloc.h" */ +/* #include */ /*------------------------------ internal #includes ---------------------- */ diff --git a/src/icxxabi.cc b/src/kernel/icxxabi.cc similarity index 100% rename from src/icxxabi.cc rename to src/kernel/icxxabi.cc diff --git a/src/libc_calls.cc b/src/kernel/libc_calls.cc similarity index 100% rename from src/libc_calls.cc rename to src/kernel/libc_calls.cc diff --git a/src/kernel/initrd.cc b/src/kernel/sys/fs/initrd.cc similarity index 99% rename from src/kernel/initrd.cc rename to src/kernel/sys/fs/initrd.cc index 4b1cae9b2..3ffad7323 100644 --- a/src/kernel/initrd.cc +++ b/src/kernel/sys/fs/initrd.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "initrd.h" +#include #include #include #include diff --git a/src/kernel/acpi-manager.cc b/src/kernel/sys/hw/acpi-manager.cc similarity index 98% rename from src/kernel/acpi-manager.cc rename to src/kernel/sys/hw/acpi-manager.cc index 2e18982ca..467311358 100644 --- a/src/kernel/acpi-manager.cc +++ b/src/kernel/sys/hw/acpi-manager.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "acpi-manager.h" +#include #include #include diff --git a/src/kernel/acpica-platform.cc b/src/kernel/sys/hw/acpica-platform.cc similarity index 99% rename from src/kernel/acpica-platform.cc rename to src/kernel/sys/hw/acpica-platform.cc index 81f0727ac..fe6ea0141 100644 --- a/src/kernel/acpica-platform.cc +++ b/src/kernel/sys/hw/acpica-platform.cc @@ -17,7 +17,7 @@ #include #include #include -#include +#include RT_INC_IO using namespace rt; diff --git a/src/kernel/fileio.cc b/src/kernel/sys/io/fileio.cc similarity index 98% rename from src/kernel/fileio.cc rename to src/kernel/sys/io/fileio.cc index 9d99e651e..ee602121e 100644 --- a/src/kernel/fileio.cc +++ b/src/kernel/sys/io/fileio.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "fileio.h" +#include #include FILE* stdin_get() { diff --git a/src/kernel/heap-snapshot.cc b/src/kernel/sys/memory/heap-snapshot.cc similarity index 98% rename from src/kernel/heap-snapshot.cc rename to src/kernel/sys/memory/heap-snapshot.cc index 4039c8b71..81b10cbf7 100644 --- a/src/kernel/heap-snapshot.cc +++ b/src/kernel/sys/memory/heap-snapshot.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "heap-snapshot.h" +#include #include namespace rt { diff --git a/src/kernel/mem-manager.cc b/src/kernel/sys/memory/mem-manager.cc similarity index 99% rename from src/kernel/mem-manager.cc rename to src/kernel/sys/memory/mem-manager.cc index 967e500fe..7e1060bf7 100644 --- a/src/kernel/mem-manager.cc +++ b/src/kernel/sys/memory/mem-manager.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "mem-manager.h" +#include #include #include #include diff --git a/src/kernel/thread-manager.cc b/src/kernel/sys/thread/thread-manager.cc similarity index 98% rename from src/kernel/thread-manager.cc rename to src/kernel/sys/thread/thread-manager.cc index 83e0d8d0d..d66ef9771 100644 --- a/src/kernel/thread-manager.cc +++ b/src/kernel/sys/thread/thread-manager.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "thread-manager.h" +#include #include #include #include diff --git a/src/kernel/thread.cc b/src/kernel/sys/thread/thread.cc similarity index 99% rename from src/kernel/thread.cc rename to src/kernel/sys/thread/thread.cc index 3654a2eb0..8b3f9ac7b 100644 --- a/src/kernel/thread.cc +++ b/src/kernel/sys/thread/thread.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "thread.h" +#include #include #include #include diff --git a/src/kernel/engine.cc b/src/kernel/sys/v8/engine.cc similarity index 98% rename from src/kernel/engine.cc rename to src/kernel/sys/v8/engine.cc index 109d87851..3d222b92a 100644 --- a/src/kernel/engine.cc +++ b/src/kernel/sys/v8/engine.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "engine.h" +#include #include #include diff --git a/src/kernel/engines.cc b/src/kernel/sys/v8/engines.cc similarity index 97% rename from src/kernel/engines.cc rename to src/kernel/sys/v8/engines.cc index 6ef03c4de..84450e5b5 100644 --- a/src/kernel/engines.cc +++ b/src/kernel/sys/v8/engines.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "engines.h" +#include #include #include diff --git a/src/kernel/native-object.cc b/src/kernel/sys/v8/native-object.cc similarity index 97% rename from src/kernel/native-object.cc rename to src/kernel/sys/v8/native-object.cc index 6d856f10b..9ba8f3591 100644 --- a/src/kernel/native-object.cc +++ b/src/kernel/sys/v8/native-object.cc @@ -12,14 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "native-object.h" -#include +#include +#include RT_INC_IO #include #include #include #include #include #include +#include #include #include #include @@ -384,9 +385,42 @@ NATIVE_FUNCTION(NativesObject, SystemInfo) { obj->Set(context, s_events_count, v8::Uint32::NewFromUnsigned(iv8, ev_count)); } + { + auto cpu_count = static_cast(GLOBAL_platform()->cpu_count()); + LOCAL_V8STRING(s_cpu_count,"cpuCount"); + obj->Set(context,s_cpu_count,v8::Uint32::NewFromUnsigned(iv8,cpu_count)); + } + args.GetReturnValue().Set(obj); } +NATIVE_FUNCTION(NativesObject,Cpuid) { + PROLOGUE_NOTHIS; + USEARG(0); + VALIDATEARG(0, UINT32, "argument 0 is not a uint32 number value"); + uint32_t code = (arg0.As())->Value(); + uint32_t a = 0; + uint32_t d = 0; + Cpu::Cpuid(code,&a,&d); + + auto obj = v8::Object::New(iv8); + + auto a_val = static_cast(a); + LOCAL_V8STRING(s_a,"a"); + obj->Set(context,s_a,v8::Uint32::NewFromUnsigned(iv8,a_val)); + + auto d_val = static_cast(d); + LOCAL_V8STRING(s_d,"d"); + obj->Set(context,s_d,v8::Uint32::NewFromUnsigned(iv8,d_val)); + + args.GetReturnValue().Set(obj); +} + +NATIVE_FUNCTION(NativesObject,Arch) { + PROLOGUE_NOTHIS; + args.GetReturnValue().Set(v8::String::NewFromUtf8(iv8,Cpu::Arch(),v8::NewStringType::kNormal).ToLocalChecked()); +} + NATIVE_FUNCTION(NativesObject, BufferAddress) { PROLOGUE_NOTHIS; USEARG(0); diff --git a/src/kernel/native-thread.cc b/src/kernel/sys/v8/native-thread.cc similarity index 97% rename from src/kernel/native-thread.cc rename to src/kernel/sys/v8/native-thread.cc index 09ff12649..6186de51b 100644 --- a/src/kernel/native-thread.cc +++ b/src/kernel/sys/v8/native-thread.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "native-thread.h" +#include namespace rt { diff --git a/src/kernel/resource.cc b/src/kernel/sys/v8/resource.cc similarity index 95% rename from src/kernel/resource.cc rename to src/kernel/sys/v8/resource.cc index c306c0b99..eec12d716 100644 --- a/src/kernel/resource.cc +++ b/src/kernel/sys/v8/resource.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "resource.h" +#include namespace rt { diff --git a/src/kernel/runtime-state.cc b/src/kernel/sys/v8/runtime-state.cc similarity index 98% rename from src/kernel/runtime-state.cc rename to src/kernel/sys/v8/runtime-state.cc index f81ae7982..b0798a86c 100644 --- a/src/kernel/runtime-state.cc +++ b/src/kernel/sys/v8/runtime-state.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "runtime-state.h" +#include namespace rt { diff --git a/src/kernel/template-cache.cc b/src/kernel/sys/v8/template-cache.cc similarity index 98% rename from src/kernel/template-cache.cc rename to src/kernel/sys/v8/template-cache.cc index c922c38bf..96a87fcc3 100644 --- a/src/kernel/template-cache.cc +++ b/src/kernel/sys/v8/template-cache.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "template-cache.h" +#include #include #include #include @@ -107,6 +107,8 @@ v8::Local TemplateCache::NewContext() { SET_SYSCALL("takeHeapSnapshot", NativesObject::TakeHeapSnapshot); SET_SYSCALL("memoryInfo", NativesObject::MemoryInfo); SET_SYSCALL("systemInfo", NativesObject::SystemInfo); + SET_SYSCALL("cpuid", NativesObject::Cpuid); + SET_SYSCALL("arch", NativesObject::Arch); SET_SYSCALL("reboot", NativesObject::Reboot); // Low level system access diff --git a/src/kernel/trace.cc b/src/kernel/sys/v8/trace.cc similarity index 96% rename from src/kernel/trace.cc rename to src/kernel/sys/v8/trace.cc index 9d979dc59..c5fd6bc6c 100644 --- a/src/kernel/trace.cc +++ b/src/kernel/sys/v8/trace.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "trace.h" +#include #include namespace rt { diff --git a/src/kernel/transport.cc b/src/kernel/sys/v8/transport.cc similarity index 99% rename from src/kernel/transport.cc rename to src/kernel/sys/v8/transport.cc index 5b467b9ad..b06d05502 100644 --- a/src/kernel/transport.cc +++ b/src/kernel/sys/v8/transport.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "transport.h" +#include #include #include #include diff --git a/src/kernel/v8platform.cc b/src/kernel/sys/v8/v8platform.cc similarity index 98% rename from src/kernel/v8platform.cc rename to src/kernel/sys/v8/v8platform.cc index 55b5075cb..23fd5d8f8 100644 --- a/src/kernel/v8platform.cc +++ b/src/kernel/sys/v8/v8platform.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "v8platform.h" +#include #include #include #include diff --git a/src/kernel/v8sampler.cc b/src/kernel/sys/v8/v8sampler.cc similarity index 100% rename from src/kernel/v8sampler.cc rename to src/kernel/sys/v8/v8sampler.cc diff --git a/src/kernel/v8utils.cc b/src/kernel/sys/v8/v8utils.cc similarity index 95% rename from src/kernel/v8utils.cc rename to src/kernel/sys/v8/v8utils.cc index 9855ae54b..db0a8aa04 100644 --- a/src/kernel/v8utils.cc +++ b/src/kernel/sys/v8/v8utils.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "v8utils.h" +#include namespace rt { diff --git a/src/kernel/crc32.cc b/src/kernel/utils/crc32.cc similarity index 99% rename from src/kernel/crc32.cc rename to src/kernel/utils/crc32.cc index cb3a351fa..251deba0b 100644 --- a/src/kernel/crc32.cc +++ b/src/kernel/utils/crc32.cc @@ -1,4 +1,4 @@ -#include "crc32.h" +#include namespace rt { diff --git a/src/kernel/logger.cc b/src/kernel/utils/logger.cc similarity index 97% rename from src/kernel/logger.cc rename to src/kernel/utils/logger.cc index b9850b54d..19f828322 100644 --- a/src/kernel/logger.cc +++ b/src/kernel/utils/logger.cc @@ -12,11 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "logger.h" +#include #include -// TODO: remove arch header -#include +#include RT_INC_IO namespace rt {