github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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 switch hcrange { 100 case 1: 101 offset = 0xf000 102 maxhc = 0xf810 103 case 2: 104 offset = 0xef00 105 maxhc = 0xef20 106 } 107 hc := gen.r.Intn((maxhc-offset)/4)*4 + offset 108 gen.byte(imap.ld64(3, uint64(hc))) 109 for i := 4; i < n+4; i++ { 110 gen.byte(imap.ld64(uint(i), gen.r.Uint64())) 111 } 112 gen.byte(imap.sc(lev)) 113 } 114 115 func (gen *generator) rtas() { 116 imap := gen.imap 117 118 addr := iset.GenerateInt(gen.cfg, gen.r, 8) 119 token := uint32(gen.r.Intn(8) << 24) // There are only 4 tokens handled by KVM and it is BigEndian. 120 reg := uint(iset.GenerateInt(gen.cfg, gen.r, 4)) 121 122 gen.byte(imap.ldgpr32(reg, reg+uint(1), addr, token)) 123 for i := 0; i < gen.r.Intn(4)+1; i++ { 124 gen.byte(imap.ldgpr32(reg, reg+uint(1), addr+uint64(i*4), 125 uint32(iset.GenerateInt(gen.cfg, gen.r, 4)))) 126 } 127 gen.byte(imap.ld64(3, 0xF000)) // 0xF000 is a custom H_RTAS hypercall 128 gen.byte(imap.ld64(4, addr)) 129 130 gen.byte(imap.sc(1)) 131 } 132 133 func (gen *generator) rfid() { 134 imap := gen.imap 135 tmpreg := uint(gen.r.Intn(32)) 136 137 // SRR0 contains a PC 138 gen.byte(imap.ld64(tmpreg, iset.GenerateInt(gen.cfg, gen.r, 8))) 139 gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr0})) 140 141 // SRR1 contains an MSR 142 gen.byte(imap.ld64(tmpreg, gen.r.Uint64())) 143 gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr1})) 144 145 gen.byte(imap["rfid"].enc(map[string]uint{})) 146 }