ひまわり

はやく人間になりたい

Untethered lowRISC(RISC-V)について

Untetheredとは簡単にいうと、”他のメインのプロセッサの支援を得ずに直にI/O使うことができる実装”のことである。
この理解についてはIRCで説明が流れていたので間違っていないはず。

これだけだと分かりづらいので、
まずlowRISCにおけるtetheredについてを説明する。

Tethered とは?

lowRISCは初期段階としてzedboardの上で実装された。
これがRelease version 0.1(tagged memory)である。

tagged memoryが何なのかはもう少し理解が進んだらまとめようと思う。

このversion 0.1がtetheredな実装で、zedboardはAll Programable SoC(AP SoC)(AlteraではSoC FPGA?)と呼ばれるZynq7000 AP SoCを搭載し、
これは、以下のようにARMコアを持つPS(Processing system)部とPE(Programable Logic)部に分かれている
PS部とPL部との接続にAXIが使われている(lowRISCはNASTI)。

Zynq-7000 All Programmable SoC Overviewより抜粋 f:id:himaaaatti:20160826203821p:plain

分かりづらいが上の大部分を占めているのがProcessing System。

RocketChip(lowRISC Chip)からとの関係の図をlowRISCより
zynq_struct

lowRISCのコアは、PL部に実装されI/O(メモリ、SDなど)はPS部経由でアクセスしている。
この利点は、
自前のメモリやI/Oのコントローラを実装しなくとも、AXIのバスを通じてアクセスができることや、 メモリを共有*1するため、lowRISCが起動する前に、BIOSに当たる処理*2を行うことができることで、 システムを一旦動かすことができるのでこの方法を選択したのだと思う。

そして、
このPS部に実装の一部を担わせるシステムの事を"tethered"と言うのだと自分は理解している。 

Untetheredとは?

以上のことより、
一旦の実装のTetheredから、メモリ、I/Oコントローラーを実装しプロセッサシステムとして独立したものを"Untethered"と呼んでいる。

この文章は間違いを含んでいる可能性があるので、コメントなどで訂正をもらえると嬉しいです。

*1:lowRISCからは後半の256MBしか見えないようだが、どこでこれを実現しているのかわからない。

*2:riscv-fesvr

SamsungがIoTにRISC-Vも視野に入れてるっぽい

昨日RISC-V HWのメーリスに投げられてた。 ARMの代わりにRISC-Vを考えていて質問と言う感じ。

https://groups.google.com/a/groups.riscv.org/forum/#!topic/hw-dev/kF8ttagAPA0

自分が思っているよりRISC-Vは現実的なところまで来ているのだろうか

*V-Scaleしらなかった

はじめて読むQtile

Qtileを使い始めて、1年くらい立ったのでそろそろ何かに残そうとこの記事を書いた。

f:id:himaaaatti:20160413200151p:plain

A full-featured, hackable tiling window manager written and configured in Python http://www.qtile.org/より

  • なぜQtileなのか

パソコンを扱っている人、すべてが抱える問題の一つにRSI*1があります。 この問題、正面から取り組んだウィンドウマネージャーがQtileです。

Save your wrists from RSI by ditching the mouse and driving with the keyboard. http://www.qtile.org/より

他にも多くの、タイル型ウィンドウマネージャーがあるのですが、なぜこれを自分が選んだかというと、 Pythonで書かれ、haskellluaよりはまだコードを読むことができたことが大きいと思います。  

そして、てっとり速くエヴァンジェリストになるためには、マイナーなものを選ぶ必要があったからです。

ウィンドウマネージャー迷っててという方には一度触ってみるのもいいかもしれません。 詳しくは公式ホームページを眺めてみてください

  • はじめかた

Arch,Fedora,Funtoo,Ubuntu方はそれぞれのパッケージマネージャーから入れられるみたいなので、ドキュメントを参考に

Sourceから入れる方法もドキュメントにあるのですが、ハマりポイントとしては、cairoを内部で使っていて、libcairo周りでしくじるかも。

  • 貢献

開発はGithubで行われていて、感覚的には毎週10個ぐらいは、issueだったり更新だったり、何かかしらの動きがある感じです。 他には、IRC*2やMailing Listもあるので覗いてみるといいかもしれません。

H8マイコンのエミュレータつくったはなし

この記事は、Aizu Advent Calendarの6日目として書かれました。

昨日 @misoton665 Kotlin(かわいい) - えびぞり。
明日 @youxkei


正確には、H8/3069FMCU動作モードは、5のみです。
そして、すべての命令は網羅できていません。

先日[自作エミュレータで学ぶx86アーキテクチャ コンピュータが動く仕組みを徹底理解!]http://uchanote.blogspot.jp/2015/08/x86.html)が出版され自分もなにか書いてみるかとことではじめました。

コードはgithub.com/himaaaatti/narcissusに上げています。

とりあえずの目標はKOZOSが動くことで、現状ステップ11までは動いてたり、動いていなかったり

H8/3069F

マニュアル(http://nsa.kpu-m.ac.jp/gijutu/h8/docs/h8_3069f.pdf)が公開されているので、ここから抜粋して 簡単にH8/3069Fについての説明を

  • 概要 f:id:himaaaatti:20151206193450p:plain

  • 特徴 f:id:himaaaatti:20151206193400p:plain

いろいろ上げても大変なのでここらへんに

流れ

命令が可変長なので、メモリから頭2 Byte読んでそれに応じて書いたり、読んだり

デバッグ

かすかにgdb remote debugができたり、できなかったり
(single step, break point, continue)
流石にもうすこし使えるようにいつかしたい

gdb remote protocolについてはここ

これから

  • KOZOSが動くようになったら、一通りの命令は対応して、周辺機器対応も
  • まじめに生きる
  • がんばる

なにかあればgithubなりtwitterなりで連絡をお願いします。
コードに対するあれやこれなコメントも期待して待ってます

システムコールを呼べる様にするまで

この記事は、自作OS Advent calendar 23 日目です。

今回はsystem callについて書きました。sysenter/sysexitではなくintによる割込みゲートを使った実装です。

自分の自作OSは、IA-32,pentium 4とそれ以降のアーキテクチャ*1を想定しています。
なので今回もこれを前提に書きます。 idtについての簡単な知識があることを前提に書きますが、自分が理解していないところがあるかもしれせん。

記事の内容に関して、不明な点や間違いがあれば指摘してもらえればと思います。

自分のコードは、30日自作OS入門に影響をいろいろと受けていて、idtのエントリの登録もこの本に従っていました。 しかし、xv6やminixの割り込みの設定を見ると、idtに直接handlerを登録しておらず、 この理由として、ハードウェア依存を減らす為だと思っています。*2

基本的にxv6の実装を参考にしているので、その部分の説明をしたいと思います。 xv6の実装は、 vectors.plで生成されるvectors.Sに登録するhandlerがひたすらあって、 これらが、idtに登録されています。
vectors.Sの一部

.globl alltraps
.globl vector0
vector0:
    pushl $0
    pushl $0
    jmp alltraps

.globl vector1
vector1:
    pushl $0
    pushl $1
    jmp alltraps
       .
       .
       .
.globl vector255
vector255:
    pushl $0
    pushl $255
    jmp alltraps

# vector table
.data
.globl vectors
vectors:
    .long vector0
    .long vector1
      .
      .
      .
    .long vector255

そのhandlerで何をしているかというと、
はじめの2個のpushで、trapframeの一部をstackを使って作っているのですが、
このtrapframeとはx86.hの中にある

struct trapframe {

    struct trapframe {
  // registers as pushed by pusha
  uint edi;
  uint esi;
  uint ebp;
  uint oesp;      // useless & ignored
  uint ebx;
  uint edx;
  uint ecx;
  uint eax;

  // rest of trap frame
  ushort gs;
  ushort padding1;
  ushort fs;
  ushort padding2;
  ushort es;
  ushort padding3;
  ushort ds;
  ushort padding4;
  uint trapno;

  // below here defined by x86 hardware
  uint err;
  uint eip;
  ushort cs;
  ushort padding5;
  uint eflags;

  // below here only when crossing rings, such as from user to kernel
  uint esp;
  ushort ss;
  ushort padding6;
};

で、vectorの一つ目のpushは
uint err; の部分で、エラーコードがある例外の割り込みの際にはpushしていません。 例として14番のpage faultの例外はエラーコードが積まれるので

vector14:
    pushl $14
    jmp alltraps

となっています。 uint err;
より下に定義してある、ものはCPUによって自動でスタックに積まれるので*3
ここでは特に触らない。

そして,alltrapsの実装はtrapasm.Sにあり

#include "mmu.h"

  # vectors.S sends all traps here.
.globl alltraps
alltraps:
  # Build trap frame.
  pushl %ds
  pushl %es
  pushl %fs
  pushl %gs
  pushal
  
  # Set up data and per-cpu segments.
  movw $(SEG_KDATA<<3), %ax
  movw %ax, %ds
  movw %ax, %es
  movw $(SEG_KCPU<<3), %ax
  movw %ax, %fs
  movw %ax, %gs

  # Call trap(tf), where tf=%esp
  pushl %esp
  call trap
  addl $4, %esp

  # Return falls through to trapret...
.globl trapret
trapret:
  popal
  popl %gs
  popl %fs
  popl %es
  popl %ds
  addl $0x8, %esp  # trapno and errcode
  iret

trapframeの続きをスタックに積んでいき、 call trap の前にespをスタックにPushすることで、今まで積んだものをtrapframeとして
trapの引数として渡しています。

そして、実際の割り込みの動作をしているtrap関数です。

void
trap(struct trapframe *tf)
{
  if(tf->trapno == T_SYSCALL){
    if(proc->killed)
      exit();
    proc->tf = tf;
    syscall();
    if(proc->killed)
      exit();
    return;
  }

  switch(tf->trapno){
  case T_IRQ0 + IRQ_TIMER:
    if(cpu->id == 0){
      acquire(&tickslock);
      ticks++;
      wakeup(&ticks);
      release(&tickslock);
    }
    lapiceoi();
    break;
  case T_IRQ0 + IRQ_IDE:
    ideintr();
    lapiceoi();
    break;
  case T_IRQ0 + IRQ_IDE+1:
    // Bochs generates spurious IDE1 interrupts.
    break;
  case T_IRQ0 + IRQ_KBD:
    kbdintr();
    lapiceoi();
    break;
  case T_IRQ0 + IRQ_COM1:
    uartintr();
    lapiceoi();
    break;
  case T_IRQ0 + 7:
  case T_IRQ0 + IRQ_SPURIOUS:
    cprintf("cpu%d: spurious interrupt at %x:%x\n",
            cpu->id, tf->cs, tf->eip);
    lapiceoi();
    break;


  //PAGEBREAK: 13
  default:
    if(proc == 0 || (tf->cs&3) == 0){
      // In kernel, it must be our mistake.
      cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
          >    tf->trapno, cpu->id, tf->eip, rcr2());
      panic("trap");
    }
    // In user space, assume process misbehaved.
    cprintf("pid %d %s: trap %d err %d on cpu %d "
            "eip 0x%x addr 0x%x--kill proc\n",
            proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, 
            rcr2());
    proc->killed = 1;
  }

  // Force process exit if it has been killed and is in user space.
  // (If it is still executing in the kernel, let it keep running 
  // until it gets to the regular system call return.)
  if(proc && proc->killed && (tf->cs&3) == DPL_USER)
    exit();

  // Force process to give up CPU on clock tick.
  // If interrupts were on while locks held, would need to check nlock.
  if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
    yield();

  // Check if the process has been killed since we yielded
  if(proc && proc->killed && (tf->cs&3) == DPL_USER)
    exit();
}

あとは、引数でもらったtrapframeのtrapnoを使ってそれぞれの処理に振り分けてます。
system_call()では中でeaxを使ってどのシステムコールなのかを特定していました。

自分の割込みの基本的な実装は同じなのですが、userとkernelのどちらからの割込みでも同じstackframeを
使っていることが気に入らなかったので、minixを参考に以下の様にしました。

#define IS_INT_IN_KERNEL(displ, label) \
    cmpl $2, displ(%esp) ;\
    je label

このマクロを使って

.globl system_call
system_call:
    IS_INT_IN_KERNEL(12, system_call_by_kernel)

system_call_by_user:
    #割込みの際に特権が変わった場合の処理(esp, ssが余分にstackに積まれる)
system_call_by_kernel:
    push %eax
    call system_call_handler
    iret

今のところこのようにsystem callを実装しました。
実は、現状ユーザープロセスを動かせていないので、特権が変わるような割込みのテストができてないので
問題を抱えているかもしれません。

当初はsysenterだけ実装しようと思っていたのですが、intによるソフトウェア割込みと話が違いすぎたので
別の記事としていつか上げたられたらいいなと思います。

余談
qemui386-systemってCR4のpage-size extensionが使えることに驚きました。

参考


IA-32 インテル® アーキテクチャー・ソフトウェア・デベロッパーズ・マニュアル、下巻: システム・プログラミング・ガイド http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev_Man_Vol3_i.pdf 

xv6

minix3

Operating Systems Design and Implementation

*1:page size extensionを使っているため。

*2:違ったり他の原因があれば教えてください。

*3:特権が変わらなかった時は、下の3つはstackに乗らないが、stackframeとして引数に渡しているのは問題になると思ったが、参照しない限り問題はないということなのだろうか?

寝袋の民

この記事はラボライフアドベントカレンダー、19日目の記事です。

突然思い立ったので参加させてもらいました。

今年ラボに配属されて半年ほどがたち、冬がやって来ました。 ここで問題が発生します。そう雪です。

今週の大寒波で大学へ来るのも命がけですよね、 登校と下校で命を落とすおそれがある

ということは、もう僕達に選択肢は2つしかありません。

大学に来ない or 大学から出ない 

ですね。

僕には出席という使命があるのであるので大学から出ない方にしました。

ここから、やっと本題なのですが ラボに泊まるということで、寝袋がたまたま、お家にあったので持ってきてみました。 そして一回ダンボール敷いて寝てみたのですが、

いろいろ、つらかった

そこで、生活を快適にするグッズを紹介します。

  1. 長座布団   床の硬さと冷たさが改善されてso good

  2. 枕(クッション)  朝の首の痛さから解法されました。。

  3. タオルケット  これが真髄なのですが、2つの不満が解決しました。  一つ目に、僕が使っている寝袋が安物なので薄くて寒い、そもそも冬使うようなものでなかった。  もうひとつ、ビニール感じな素材なので汗とか吸うようなものではないのでで、少しでも汗を書くとはだによろしくなかった。
     

どれも某とりでお値段以上な感じでかつ、安くてにはいります。 それぞれ、1000 + 600 + 600 円ぐらいでした。 生活費を削ってどうにかなるレベルで良かったです。

この3つの神器によって今は快適な生活を送っています。

あなたも、寝袋という新しい可能性を見てみませんか?

brainf*ck!!

お昼ごろ思い立ってpython3でbrainf*ck書いてみた。

https://github.com/himaaaatti/brainf-ck

 

結構時間かかったのと、pythonの組み込み変数の'__debug__' と

assert文の使い方がわかったのでよかったです(こなみかん