github.com/transparency-dev/armored-witness-os@v0.1.3-0.20240514084412-27eef7325168/trusted_os/handler.go (about)

     1  // Copyright 2022 The Armored Witness OS authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"fmt"
    19  	"log"
    20  
    21  	"github.com/usbarmory/tamago/arm"
    22  	"github.com/usbarmory/tamago/bits"
    23  	"github.com/usbarmory/tamago/soc/nxp/imx6ul"
    24  
    25  	"github.com/usbarmory/GoTEE/monitor"
    26  	"github.com/usbarmory/GoTEE/syscall"
    27  )
    28  
    29  const CPSR_FIQ = 6
    30  
    31  var (
    32  	appletHandlerG uint32
    33  	appletHandlerP uint32
    34  )
    35  
    36  var irqHandler = make(map[int]func())
    37  
    38  // defined in handler.s
    39  func wakeHandler(g uint32, p uint32)
    40  
    41  func isr() (err error) {
    42  	irq, end := imx6ul.GIC.GetInterrupt(true)
    43  
    44  	if end != nil {
    45  		close(end)
    46  	}
    47  
    48  	if handle, ok := irqHandler[irq]; ok {
    49  		handle()
    50  		return nil
    51  	}
    52  
    53  	return fmt.Errorf("unexpected IRQ %d", irq)
    54  }
    55  
    56  func handleInterrupts() {
    57  	arm.RegisterInterruptHandler()
    58  
    59  	for {
    60  		arm.WaitInterrupt()
    61  
    62  		if err := isr(); err != nil {
    63  			log.Printf("SM IRQ handling error: %v", err)
    64  		}
    65  	}
    66  }
    67  
    68  func fiqHandler(ctx *monitor.ExecCtx) (_ error) {
    69  	// We want to handle FIQs only when raised from User mode (e.g.
    70  	// Trusted Applet running) as we need to wake up the applet
    71  	// handler with FIQs masked.
    72  	//
    73  	// If we get here from System mode (e.g. Trusted OS running)
    74  	// resume execution with FIQ masked (FIQs are masked soon as
    75  	// possible when switching back to the Trusted OS but we can be
    76  	// raced between exception vector and disabling instruction).
    77  	if _, saved := ctx.Mode(); saved != arm.USR_MODE {
    78  		bits.Set(&ctx.SPSR, CPSR_FIQ)
    79  		return
    80  	}
    81  
    82  	if err := isr(); err != nil {
    83  		log.Printf("SM FIQ handling error: %v", err)
    84  	}
    85  
    86  	// mask FIQs, applet handler will request unmasking when done
    87  	bits.Set(&ctx.SPSR, CPSR_FIQ)
    88  
    89  	wakeHandler(appletHandlerG, appletHandlerP)
    90  
    91  	return
    92  }
    93  
    94  // The exception handler is responsible for the following tasks:
    95  //   - override GoTEE default handling for SYS_WRITE to avoid interleaved logs
    96  //   - serve RX/TX syscalls for Ethernet packets I/O
    97  //   - service Ethernet IRQs for incoming packets
    98  //
    99  // As a precaution against an unexpectedly long syscall handler, we also service
   100  // the watchdog whenever we transmit a packet.
   101  func handler(ctx *monitor.ExecCtx) (err error) {
   102  	switch ctx.ExceptionVector {
   103  	case arm.FIQ:
   104  		return fiqHandler(ctx)
   105  	case arm.SUPERVISOR:
   106  		switch ctx.A0() {
   107  		case syscall.SYS_WRITE:
   108  			return bufferedStdoutLog(byte(ctx.A1()))
   109  		case RX:
   110  			return rxFromApplet(ctx)
   111  		case TX:
   112  			// Ensure the watchdog doesn't get starved by servicing it here as a precaution.
   113  			// The logic is that if we're either sending data out or ACKing received
   114  			// packets then we're almost certainly not wedged, so servicing the dog
   115  			// is reasonable.
   116  			imx6ul.WDOG2.Service(watchdogTimeout)
   117  			return txFromApplet(ctx)
   118  		case FIQ:
   119  			bits.Clear(&ctx.SPSR, CPSR_FIQ)
   120  		case FREQ:
   121  			return imx6ul.SetARMFreq(uint32(ctx.A1()))
   122  		default:
   123  			return monitor.SecureHandler(ctx)
   124  		}
   125  	default:
   126  		log.Fatalf("unhandled exception %x", ctx.ExceptionVector)
   127  	}
   128  
   129  	return
   130  }