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 }