github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/ifuzz/powerpc/pseudo.go (about) 1 // Copyright 2020 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package powerpc 5 6 import ( 7 "math/rand" 8 9 "github.com/google/syzkaller/pkg/ifuzz/iset" 10 ) 11 12 const ( 13 // Valid hcall humbers at the momemt are: 4..0x450. 14 MaxHcall = 0x450 // MAX_HCALL 15 SprnSrr0 = 0x01A // pc for rfid (SPRN_SRR0) 16 SprnSrr1 = 0x01B // msr for rfid (SPRN_SRR1) 17 ) 18 19 // nolint:dupl 20 func (insnset *InsnSet) initPseudo() { 21 insnset.Insns = append(insnset.Insns, &Insn{ 22 Name: "PSEUDO_hypercall", 23 Priv: true, 24 Pseudo: true, 25 generator: func(cfg *iset.Config, r *rand.Rand) []byte { 26 gen := makeGen(insnset, cfg, r) 27 gen.sc(1) 28 return gen.text 29 }, 30 }) 31 insnset.Insns = append(insnset.Insns, &Insn{ 32 Name: "PSEUDO_syscall", 33 Priv: true, 34 Pseudo: true, 35 generator: func(cfg *iset.Config, r *rand.Rand) []byte { 36 gen := makeGen(insnset, cfg, r) 37 gen.sc(0) 38 return gen.text 39 }, 40 }) 41 insnset.Insns = append(insnset.Insns, &Insn{ 42 Name: "PSEUDO_ultracall", 43 Priv: true, 44 Pseudo: true, 45 generator: func(cfg *iset.Config, r *rand.Rand) []byte { 46 gen := makeGen(insnset, cfg, r) 47 gen.sc(2) 48 return gen.text 49 }, 50 }) 51 insnset.Insns = append(insnset.Insns, &Insn{ 52 Name: "PSEUDO_rtas", 53 Priv: true, 54 Pseudo: true, 55 generator: func(cfg *iset.Config, r *rand.Rand) []byte { 56 gen := makeGen(insnset, cfg, r) 57 gen.rtas() 58 return gen.text 59 }, 60 }) 61 insnset.Insns = append(insnset.Insns, &Insn{ 62 Name: "PSEUDO_rfid", 63 Priv: true, 64 Pseudo: true, 65 generator: func(cfg *iset.Config, r *rand.Rand) []byte { 66 gen := makeGen(insnset, cfg, r) 67 gen.rfid() 68 return gen.text 69 }, 70 }) 71 } 72 73 type generator struct { 74 imap insnSetMap 75 cfg *iset.Config 76 r *rand.Rand 77 text []byte 78 } 79 80 func makeGen(insnset *InsnSet, cfg *iset.Config, r *rand.Rand) *generator { 81 return &generator{ 82 imap: insnset.insnMap, 83 cfg: cfg, 84 r: r, 85 } 86 } 87 88 func (gen *generator) byte(v []byte) { 89 gen.text = append(gen.text, v...) 90 } 91 92 func (gen *generator) sc(lev uint) { 93 imap := gen.imap 94 95 n := gen.r.Intn(9) 96 hcrange := gen.r.Intn(3) 97 offset := 4 98 maxhc := MaxHcall 99 if hcrange == 1 { 100 offset = 0xf000 101 maxhc = 0xf810 102 } else if hcrange == 2 { 103 offset = 0xef00 104 maxhc = 0xef20 105 } 106 hc := gen.r.Intn((maxhc-offset)/4)*4 + offset 107 gen.byte(imap.ld64(3, uint64(hc))) 108 for i := 4; i < n+4; i++ { 109 gen.byte(imap.ld64(uint(i), gen.r.Uint64())) 110 } 111 gen.byte(imap.sc(lev)) 112 } 113 114 func (gen *generator) rtas() { 115 imap := gen.imap 116 117 addr := iset.GenerateInt(gen.cfg, gen.r, 8) 118 token := uint32(gen.r.Intn(8) << 24) // There are only 4 tokens handled by KVM and it is BigEndian. 119 reg := uint(iset.GenerateInt(gen.cfg, gen.r, 4)) 120 121 gen.byte(imap.ldgpr32(reg, reg+uint(1), addr, token)) 122 for i := 0; i < gen.r.Intn(4)+1; i++ { 123 gen.byte(imap.ldgpr32(reg, reg+uint(1), addr+uint64(i*4), 124 uint32(iset.GenerateInt(gen.cfg, gen.r, 4)))) 125 } 126 gen.byte(imap.ld64(3, 0xF000)) // 0xF000 is a custom H_RTAS hypercall 127 gen.byte(imap.ld64(4, addr)) 128 129 gen.byte(imap.sc(1)) 130 } 131 132 func (gen *generator) rfid() { 133 imap := gen.imap 134 tmpreg := uint(gen.r.Intn(32)) 135 136 // SRR0 contains a PC 137 gen.byte(imap.ld64(tmpreg, iset.GenerateInt(gen.cfg, gen.r, 8))) 138 gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr0})) 139 140 // SRR1 contains an MSR 141 gen.byte(imap.ld64(tmpreg, gen.r.Uint64())) 142 gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr1})) 143 144 gen.byte(imap["rfid"].enc(map[string]uint{})) 145 }